diff options
Diffstat (limited to 'bridges')
259 files changed, 69351 insertions, 0 deletions
diff --git a/bridges/inc/bridges/cpp_uno/bridge.hxx b/bridges/inc/bridges/cpp_uno/bridge.hxx new file mode 100644 index 000000000000..26bb101017c3 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/bridge.hxx @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _BRIDGES_CPP_UNO_BRIDGE_HXX_ +#define _BRIDGES_CPP_UNO_BRIDGE_HXX_ + +#include <bridges/cpp_uno/bridge.h> +#include <osl/mutex.hxx> +#include <rtl/process.h> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/uno/genfunc.hxx> +#include <com/sun/star/uno/XInterface.hpp> + + +namespace CPPU_CURRENT_NAMESPACE +{ + +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppInterfaceProxy_free( uno_ExtEnvironment * pEnv, void * pProxy ) SAL_THROW( () ) +{ + cppu_cppInterfaceProxy * pThis = + static_cast< cppu_cppInterfaceProxy * >( + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pProxy ) ); + OSL_ASSERT( pEnv == pThis->pBridge->pCppEnv ); + + (*pThis->pBridge->pUnoEnv->revokeInterface)( pThis->pBridge->pUnoEnv, pThis->pUnoI ); + (*pThis->pUnoI->release)( pThis->pUnoI ); + ::typelib_typedescription_release( (typelib_TypeDescription *)pThis->pTypeDescr ); + pThis->pBridge->release(); + +#if OSL_DEBUG_LEVEL > 1 + *(int *)pProxy = 0xdeadbabe; +#endif + delete pThis; +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_Mapping_uno2cpp( + uno_Mapping * pMapping, void ** ppCppI, + void * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr ) SAL_THROW( () ) +{ + OSL_ASSERT( ppCppI && pTypeDescr ); + if (*ppCppI) + { + reinterpret_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )->release(); + *ppCppI = 0; + } + if (pUnoI) + { + cppu_Bridge * pBridge = static_cast< cppu_Mapping * >( pMapping )->pBridge; + + // get object id of uno interface to be wrapped + rtl_uString * pOId = 0; + (*pBridge->pUnoEnv->getObjectIdentifier)( pBridge->pUnoEnv, &pOId, pUnoI ); + OSL_ASSERT( pOId ); + + // try to get any known interface from target environment + (*pBridge->pCppEnv->getRegisteredInterface)( + pBridge->pCppEnv, ppCppI, pOId, pTypeDescr ); + + if (! *ppCppI) // no existing interface, register new proxy interface + { + // try to publish a new proxy (ref count initially 1) + cppu_cppInterfaceProxy * pProxy = new cppu_cppInterfaceProxy( + pBridge, reinterpret_cast< uno_Interface * >( pUnoI ), pTypeDescr, pOId ); + ::com::sun::star::uno::XInterface * pSurrogate = pProxy; + cppu_cppInterfaceProxy_patchVtable( pSurrogate, pProxy->pTypeDescr ); + + // proxy may be exchanged during registration + (*pBridge->pCppEnv->registerProxyInterface)( + pBridge->pCppEnv, reinterpret_cast< void ** >( &pSurrogate ), + (uno_freeProxyFunc)cppu_cppInterfaceProxy_free, pOId, pTypeDescr ); + + *ppCppI = pSurrogate; + } + ::rtl_uString_release( pOId ); + } +} +//__________________________________________________________________________________________________ +inline void cppu_cppInterfaceProxy::acquireProxy() SAL_THROW( () ) +{ + if (1 == osl_incrementInterlockedCount( &nRef )) + { + // rebirth of proxy zombie + // register at cpp env + void * pThis = static_cast< ::com::sun::star::uno::XInterface * >( this ); + (*pBridge->pCppEnv->registerProxyInterface)( + pBridge->pCppEnv, &pThis, (uno_freeProxyFunc)cppu_cppInterfaceProxy_free, + oid.pData, pTypeDescr ); + OSL_ASSERT( pThis == static_cast< ::com::sun::star::uno::XInterface * >( this ) ); + } +} +//__________________________________________________________________________________________________ +inline void cppu_cppInterfaceProxy::releaseProxy() SAL_THROW( () ) +{ + if (! osl_decrementInterlockedCount( &nRef )) // last release + { + // revoke from cpp env + (*pBridge->pCppEnv->revokeInterface)( + pBridge->pCppEnv, static_cast< ::com::sun::star::uno::XInterface * >( this ) ); + } +} +//__________________________________________________________________________________________________ +inline cppu_cppInterfaceProxy::cppu_cppInterfaceProxy( + cppu_Bridge * pBridge_, uno_Interface * pUnoI_, + typelib_InterfaceTypeDescription * pTypeDescr_, const ::rtl::OUString & rOId_ ) SAL_THROW( () ) + : nRef( 1 ) + , pBridge( pBridge_ ) + , pUnoI( pUnoI_ ) + , pTypeDescr( pTypeDescr_ ) + , oid( rOId_ ) +{ + pBridge->acquire(); + ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); + if (! ((typelib_TypeDescription *)pTypeDescr)->bComplete) + ::typelib_typedescription_complete( (typelib_TypeDescription **)&pTypeDescr ); + OSL_ENSURE( ((typelib_TypeDescription *)pTypeDescr)->bComplete, "### type is incomplete!" ); + (*pUnoI->acquire)( pUnoI ); + (*pBridge->pUnoEnv->registerInterface)( + pBridge->pUnoEnv, reinterpret_cast< void ** >( &pUnoI ), oid.pData, pTypeDescr ); +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_unoInterfaceProxy_free( uno_ExtEnvironment * pEnv, void * pProxy ) SAL_THROW( () ) +{ + cppu_unoInterfaceProxy * pThis = + static_cast< cppu_unoInterfaceProxy * >( + reinterpret_cast< uno_Interface * >( pProxy ) ); + OSL_ASSERT( pEnv == pThis->pBridge->pUnoEnv ); + + (*pThis->pBridge->pCppEnv->revokeInterface)( pThis->pBridge->pCppEnv, pThis->pCppI ); + pThis->pCppI->release(); + ::typelib_typedescription_release( (typelib_TypeDescription *)pThis->pTypeDescr ); + pThis->pBridge->release(); + +#if OSL_DEBUG_LEVEL > 1 + *(int *)pProxy = 0xdeadbabe; +#endif + delete pThis; +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_unoInterfaceProxy_acquire( uno_Interface * pUnoI ) SAL_THROW( () ) +{ + if (1 == osl_incrementInterlockedCount( & static_cast< cppu_unoInterfaceProxy * >( pUnoI )->nRef )) + { + // rebirth of proxy zombie + // register at uno env +#if OSL_DEBUG_LEVEL > 1 + void * pThis = pUnoI; +#endif + (*static_cast< cppu_unoInterfaceProxy * >( pUnoI )->pBridge->pUnoEnv->registerProxyInterface)( + static_cast< cppu_unoInterfaceProxy * >( pUnoI )->pBridge->pUnoEnv, + reinterpret_cast< void ** >( &pUnoI ), + (uno_freeProxyFunc)cppu_unoInterfaceProxy_free, + static_cast< cppu_unoInterfaceProxy * >( pUnoI )->oid.pData, + static_cast< cppu_unoInterfaceProxy * >( pUnoI )->pTypeDescr ); +#if OSL_DEBUG_LEVEL > 1 + OSL_ASSERT( pThis == pUnoI ); +#endif + } +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_unoInterfaceProxy_release( uno_Interface * pUnoI ) SAL_THROW( () ) +{ + if (! osl_decrementInterlockedCount( & static_cast< cppu_unoInterfaceProxy * >( pUnoI )->nRef )) + { + // revoke from uno env on last release + (*static_cast< cppu_unoInterfaceProxy * >( pUnoI )->pBridge->pUnoEnv->revokeInterface)( + static_cast< cppu_unoInterfaceProxy * >( pUnoI )->pBridge->pUnoEnv, pUnoI ); + } +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_Mapping_cpp2uno( + uno_Mapping * pMapping, void ** ppUnoI, + void * pCppI, typelib_InterfaceTypeDescription * pTypeDescr ) SAL_THROW( () ) +{ + OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" ); + if (*ppUnoI) + { + (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)( + reinterpret_cast< uno_Interface * >( *ppUnoI ) ); + *ppUnoI = 0; + } + if (pCppI) + { + cppu_Bridge * pBridge = static_cast< cppu_Mapping * >( pMapping )->pBridge; + + // get object id of interface to be wrapped + rtl_uString * pOId = 0; + (*pBridge->pCppEnv->getObjectIdentifier)( pBridge->pCppEnv, &pOId, pCppI ); + OSL_ASSERT( pOId ); + + // try to get any known interface from target environment + (*pBridge->pUnoEnv->getRegisteredInterface)( + pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr ); + + if (! *ppUnoI) // no existing interface, register new proxy interface + { + // try to publish a new proxy (refcount initially 1) + uno_Interface * pSurrogate = new cppu_unoInterfaceProxy( + pBridge, reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI ), + pTypeDescr, pOId ); + + // proxy may be exchanged during registration + (*pBridge->pUnoEnv->registerProxyInterface)( + pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ), + (uno_freeProxyFunc)cppu_unoInterfaceProxy_free, pOId, pTypeDescr ); + + *ppUnoI = pSurrogate; + } + ::rtl_uString_release( pOId ); + } +} +//__________________________________________________________________________________________________ +inline cppu_unoInterfaceProxy::cppu_unoInterfaceProxy( + cppu_Bridge * pBridge_, ::com::sun::star::uno::XInterface * pCppI_, + typelib_InterfaceTypeDescription * pTypeDescr_, const ::rtl::OUString & rOId_ ) SAL_THROW( () ) + : nRef( 1 ) + , pBridge( pBridge_ ) + , pCppI( pCppI_ ) + , pTypeDescr( pTypeDescr_ ) + , oid( rOId_ ) +{ + pBridge->acquire(); + ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); + if (! ((typelib_TypeDescription *)pTypeDescr)->bComplete) + ::typelib_typedescription_complete( (typelib_TypeDescription **)&pTypeDescr ); + OSL_ENSURE( ((typelib_TypeDescription *)pTypeDescr)->bComplete, "### type is incomplete!" ); + pCppI->acquire(); + (*pBridge->pCppEnv->registerInterface)( + pBridge->pCppEnv, reinterpret_cast< void ** >( &pCppI ), oid.pData, pTypeDescr ); + + // uno_Interface + uno_Interface::acquire = cppu_unoInterfaceProxy_acquire; + uno_Interface::release = cppu_unoInterfaceProxy_release; + uno_Interface::pDispatcher = (uno_DispatchMethod)cppu_unoInterfaceProxy_dispatch; +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_Mapping_acquire( uno_Mapping * pMapping ) SAL_THROW( () ) +{ + static_cast< cppu_Mapping * >( pMapping )->pBridge->acquire(); +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_Mapping_release( uno_Mapping * pMapping ) SAL_THROW( () ) +{ + static_cast< cppu_Mapping * >( pMapping )->pBridge->release(); +} +//__________________________________________________________________________________________________ +inline cppu_Bridge::cppu_Bridge( + uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_, + sal_Bool bExportCpp2Uno_ ) SAL_THROW( () ) + : nRef( 1 ) + , pCppEnv( pCppEnv_ ) + , pUnoEnv( pUnoEnv_ ) + , bExportCpp2Uno( bExportCpp2Uno_ ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + + aCpp2Uno.pBridge = this; + aCpp2Uno.acquire = cppu_Mapping_acquire; + aCpp2Uno.release = cppu_Mapping_release; + aCpp2Uno.mapInterface = cppu_Mapping_cpp2uno; + + aUno2Cpp.pBridge = this; + aUno2Cpp.acquire = cppu_Mapping_acquire; + aUno2Cpp.release = cppu_Mapping_release; + aUno2Cpp.mapInterface = cppu_Mapping_uno2cpp; + + (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv ); + (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv ); +} +//__________________________________________________________________________________________________ +inline cppu_Bridge::~cppu_Bridge() SAL_THROW( () ) +{ + (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv ); + (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv ); + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +inline void SAL_CALL cppu_Bridge_free( uno_Mapping * pMapping ) SAL_THROW( () ) +{ + delete static_cast< cppu_Mapping * >( pMapping )->pBridge; +} +//__________________________________________________________________________________________________ +inline void cppu_Bridge::acquire() SAL_THROW( () ) +{ + if (1 == osl_incrementInterlockedCount( &nRef )) + { + if (bExportCpp2Uno) + { + uno_Mapping * pMapping = &aCpp2Uno; + ::uno_registerMapping( + &pMapping, cppu_Bridge_free, + (uno_Environment *)pCppEnv, (uno_Environment *)pUnoEnv, 0 ); + } + else + { + uno_Mapping * pMapping = &aUno2Cpp; + ::uno_registerMapping( + &pMapping, cppu_Bridge_free, + (uno_Environment *)pUnoEnv, (uno_Environment *)pCppEnv, 0 ); + } + } +} +//__________________________________________________________________________________________________ +inline void cppu_Bridge::release() SAL_THROW( () ) +{ + if (! osl_decrementInterlockedCount( &nRef )) + { + ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp ); + } +} + +//################################################################################################## +inline void SAL_CALL cppu_ext_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) SAL_THROW( () ) +{ + OSL_ASSERT( ppMapping && pFrom && pTo ); + if (ppMapping && pFrom && pTo && pFrom->pExtEnv && pTo->pExtEnv) + { + uno_Mapping * pMapping = 0; + + if (0 == rtl_ustr_ascii_compare( pFrom->pTypeName->buffer, CPPU_CURRENT_LANGUAGE_BINDING_NAME ) && + 0 == rtl_ustr_ascii_compare( pTo->pTypeName->buffer, UNO_LB_UNO )) + { + // ref count initially 1 + pMapping = &(new cppu_Bridge( pFrom->pExtEnv, pTo->pExtEnv, sal_True ))->aCpp2Uno; + ::uno_registerMapping( + &pMapping, cppu_Bridge_free, + (uno_Environment *)pFrom->pExtEnv, + (uno_Environment *)pTo->pExtEnv, 0 ); + } + else if (0 == rtl_ustr_ascii_compare( pTo->pTypeName->buffer, CPPU_CURRENT_LANGUAGE_BINDING_NAME ) && + 0 == rtl_ustr_ascii_compare( pFrom->pTypeName->buffer, UNO_LB_UNO )) + { + // ref count initially 1 + pMapping = &(new cppu_Bridge( pTo->pExtEnv, pFrom->pExtEnv, sal_False ))->aUno2Cpp; + ::uno_registerMapping( + &pMapping, cppu_Bridge_free, + (uno_Environment *)pFrom->pExtEnv, + (uno_Environment *)pTo->pExtEnv, 0 ); + } + + if (*ppMapping) + { + (*(*ppMapping)->release)( *ppMapping ); + } + if (pMapping) + *ppMapping = pMapping; + } +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) +static ::rtl::OUString * s_pStaticOidPart = 0; +#endif + +// environment init stuff +//-------------------------------------------------------------------------------------------------- +inline const ::rtl::OUString & SAL_CALL cppu_cppenv_getStaticOIdPart() SAL_THROW( () ) +{ +#if ! (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) + static ::rtl::OUString * s_pStaticOidPart = 0; +#endif + if (! s_pStaticOidPart) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! s_pStaticOidPart) + { + ::rtl::OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); + // good guid + sal_uInt8 ar[16]; + ::rtl_getGlobalProcessId( ar ); + for ( sal_Int32 i = 0; i < 16; ++i ) + { + aRet.append( (sal_Int32)ar[i], 16 ); + } +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) + s_pStaticOidPart = new ::rtl::OUString( aRet.makeStringAndClear() ); +#else + static ::rtl::OUString s_aStaticOidPart( aRet.makeStringAndClear() ); + s_pStaticOidPart = &s_aStaticOidPart; +#endif + } + } + return *s_pStaticOidPart; +} +// functions set at environment init +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppenv_computeObjectIdentifier( + uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) SAL_THROW( () ) +{ + OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); + if (pEnv && ppOId && pInterface) + { + if (*ppOId) + { + rtl_uString_release( *ppOId ); + *ppOId = 0; + } + + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xHome( + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pInterface ), + ::com::sun::star::uno::UNO_QUERY ); + OSL_ENSURE( xHome.is(), "### query to XInterface failed!" ); + if (xHome.is()) + { + // interface + ::rtl::OUStringBuffer oid( 64 ); + oid.append( (sal_Int64)xHome.get(), 16 ); + oid.append( (sal_Unicode)';' ); + // ;environment[context] + oid.append( + *reinterpret_cast< ::rtl::OUString const * >( + &((uno_Environment *) pEnv)->pTypeName ) ); + oid.append( (sal_Unicode)'[' ); + oid.append( (sal_Int64)((uno_Environment *)pEnv)->pContext, 16 ); + // ];good guid + oid.append( cppu_cppenv_getStaticOIdPart() ); + ::rtl::OUString aRet( oid.makeStringAndClear() ); + ::rtl_uString_acquire( *ppOId = aRet.pData ); + } + } + catch (::com::sun::star::uno::RuntimeException &) + { + OSL_FAIL( "### RuntimeException occurred udring queryInterface()!" ); + } + } +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppenv_acquireInterface( uno_ExtEnvironment *, void * pCppI ) SAL_THROW( () ) +{ + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->acquire(); +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppenv_releaseInterface( uno_ExtEnvironment *, void * pCppI ) SAL_THROW( () ) +{ + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->release(); +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppenv_environmentDisposing( uno_Environment * ) SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//-------------------------------------------------------------------------------------------------- +inline void SAL_CALL cppu_cppenv_initEnvironment( uno_Environment * pCppEnv ) SAL_THROW( () ) +{ + OSL_ENSURE( pCppEnv->pExtEnv, "### expected extended environment!" ); + OSL_ENSURE( ::rtl_ustr_ascii_compare( pCppEnv->pTypeName->buffer, CPPU_CURRENT_LANGUAGE_BINDING_NAME ) == 0, "### wrong environment type!" ); + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + ((uno_ExtEnvironment *)pCppEnv)->computeObjectIdentifier = cppu_cppenv_computeObjectIdentifier; + ((uno_ExtEnvironment *)pCppEnv)->acquireInterface = cppu_cppenv_acquireInterface; + ((uno_ExtEnvironment *)pCppEnv)->releaseInterface = cppu_cppenv_releaseInterface; + pCppEnv->environmentDisposing = cppu_cppenv_environmentDisposing; +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/arraypointer.hxx b/bridges/inc/bridges/cpp_uno/shared/arraypointer.hxx new file mode 100644 index 000000000000..542be6e0f3d6 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/arraypointer.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_ARRAYPOINTER_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_ARRAYPOINTER_HXX + +#include "sal/config.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +/** + * A simple smart pointer that holds an array until it is being released. + */ +template< typename T > class ArrayPointer { +public: + ArrayPointer(T * p): p_(p) {} + + ~ArrayPointer() { delete[] p_; } + + T * release() { T * t = p_; p_ = 0; return t; } + +private: + ArrayPointer(ArrayPointer &); // not defined + void operator =(ArrayPointer &); // not defined + + T * p_; +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/bridge.hxx b/bridges/inc/bridges/cpp_uno/shared/bridge.hxx new file mode 100644 index 000000000000..4ee69e37b416 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/bridge.hxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_BRIDGE_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_BRIDGE_HXX + +#include "osl/interlck.h" +#include "sal/types.h" +#include "typelib/typedescription.h" +#include "uno/environment.h" +#include "uno/mapping.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +// private: +extern "C" typedef void SAL_CALL FreeMapping(uno_Mapping *); +FreeMapping freeMapping; + +// private: +extern "C" +typedef void SAL_CALL AcquireMapping(uno_Mapping *); +AcquireMapping acquireMapping; + +// private: +extern "C" +typedef void SAL_CALL ReleaseMapping(uno_Mapping *); +ReleaseMapping releaseMapping; + +// private: +extern "C" typedef void SAL_CALL Cpp2unoMapping( + uno_Mapping *, void **, void *, typelib_InterfaceTypeDescription *); +Cpp2unoMapping cpp2unoMapping; + +// private: +extern "C" typedef void SAL_CALL Uno2cppMapping( + uno_Mapping *, void **, void *, typelib_InterfaceTypeDescription *); +Uno2cppMapping uno2cppMapping; + +/** + * Holding environments and mappings. + */ +class Bridge { +public: + // Interface for generic/component.cxx: + + static uno_Mapping * createMapping( + uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv, + bool bExportCpp2Uno) SAL_THROW(()); + + // Interface for Cpp/UnoInterfaceProxy: + + void acquire() SAL_THROW(()); + void release() SAL_THROW(()); + + // Interface for individual CPP--UNO bridges: + + uno_ExtEnvironment * getCppEnv() { return pCppEnv; } + uno_ExtEnvironment * getUnoEnv() { return pUnoEnv; } + + uno_Mapping * getCpp2Uno() { return &aCpp2Uno; } + uno_Mapping * getUno2Cpp() { return &aUno2Cpp; } + +private: + Bridge(Bridge &); // not implemented + void operator =(Bridge); // not implemented + + Bridge( + uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_, + bool bExportCpp2Uno_) SAL_THROW(()); + + ~Bridge() SAL_THROW(()); + + struct Mapping: public uno_Mapping { + Bridge * pBridge; + }; + + oslInterlockedCount nRef; + + uno_ExtEnvironment * pCppEnv; + uno_ExtEnvironment * pUnoEnv; + + Mapping aCpp2Uno; + Mapping aUno2Cpp; + + bool bExportCpp2Uno; + + friend void SAL_CALL freeMapping(uno_Mapping * pMapping); + + friend void SAL_CALL acquireMapping(uno_Mapping * pMapping); + + friend void SAL_CALL releaseMapping(uno_Mapping * pMapping); + + friend void SAL_CALL cpp2unoMapping( + uno_Mapping * pMapping, void ** ppUnoI, void * pCppI, + typelib_InterfaceTypeDescription * pTypeDescr); + + friend void SAL_CALL uno2cppMapping( + uno_Mapping * pMapping, void ** ppCppI, void * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr); +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/cppinterfaceproxy.hxx b/bridges/inc/bridges/cpp_uno/shared/cppinterfaceproxy.hxx new file mode 100644 index 000000000000..31e19cc94d00 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/cppinterfaceproxy.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_CPPINTERFACEPROXY_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_CPPINTERFACEPROXY_HXX + +#include "osl/interlck.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "typelib/typedescription.h" +#include "uno/dispatcher.h" +#include "uno/environment.h" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +namespace com { namespace sun { namespace star { namespace uno { + class XInterface; +} } } } + +namespace bridges { namespace cpp_uno { namespace shared { + +class Bridge; + +extern "C" typedef void SAL_CALL FreeCppInterfaceProxy( + uno_ExtEnvironment * pEnv, void * pInterface); +FreeCppInterfaceProxy freeCppInterfaceProxy; + +/** + * A cpp proxy wrapping a uno interface. + */ +class CppInterfaceProxy { +public: + // Interface for Bridge: + + static com::sun::star::uno::XInterface * create( + Bridge * pBridge, uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr, + rtl::OUString const & rOId) SAL_THROW(()); + + // Interface for individual CPP--UNO bridges: + + Bridge * getBridge() { return pBridge; } + uno_Interface * getUnoI() { return pUnoI; } + typelib_InterfaceTypeDescription * getTypeDescr() { return pTypeDescr; } + rtl::OUString getOid() { return oid; } + + // non virtual methods called on incoming vtable calls #1, #2 + void acquireProxy() SAL_THROW(()); + void releaseProxy() SAL_THROW(()); + + static CppInterfaceProxy * castInterfaceToProxy(void * pInterface); + +private: + CppInterfaceProxy(CppInterfaceProxy &); // not implemented + void operator =(CppInterfaceProxy); // not implemented + + CppInterfaceProxy( + Bridge * pBridge_, uno_Interface * pUnoI_, + typelib_InterfaceTypeDescription * pTypeDescr_, + rtl::OUString const & rOId_) SAL_THROW(()); + + ~CppInterfaceProxy(); + + static com::sun::star::uno::XInterface * castProxyToInterface( + CppInterfaceProxy * pProxy); + + oslInterlockedCount nRef; + Bridge * pBridge; + + // mapping information + uno_Interface * pUnoI; // wrapped interface + typelib_InterfaceTypeDescription * pTypeDescr; + rtl::OUString oid; + + VtableFactory::Slot * vtables[1]; + + friend void SAL_CALL freeCppInterfaceProxy( + uno_ExtEnvironment * pEnv, void * pInterface); +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/types.hxx b/bridges/inc/bridges/cpp_uno/shared/types.hxx new file mode 100644 index 000000000000..0cc87864af0e --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/types.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_TYPES_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_TYPES_HXX + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +/** + * Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, + * UNSIGNED SHORT, LONG, UNSIGNED LONG, HYPER, UNSIGNED HYPER, FLOAT, DOUBLE, + * CHAR, or an enum type). + * + * @param typeClass a type class + * @return true if the given type is "simple" + */ +bool isSimpleType(typelib_TypeClass typeClass); + +/** + * Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, + * UNSIGNED SHORT, LONG, UNSIGNED LONG, HYPER, UNSIGNED HYPER, FLOAT, DOUBLE, + * CHAR, or an enum type). + * + * @param type a non-null pointer to a type description reference + * @return true if the given type is "simple" + */ +bool isSimpleType(typelib_TypeDescriptionReference const * type); + +/** + * Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, + * UNSIGNED SHORT, LONG, UNSIGNED LONG, HYPER, UNSIGNED HYPER, FLOAT, DOUBLE, + * CHAR, or an enum type). + * + * @param type a non-null pointer to a type description + * @return true if the given type is "simple" + */ +bool isSimpleType(typelib_TypeDescription const * type); + +/** + * Determines whether a type relates to an interface type (is itself an + * interface type, or might contain entities of interface type). + * + * @param type a non-null pointer to a type description + * @return true if the given type relates to an interface type + */ +bool relatesToInterfaceType(typelib_TypeDescription const * type); + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/unointerfaceproxy.hxx b/bridges/inc/bridges/cpp_uno/shared/unointerfaceproxy.hxx new file mode 100644 index 000000000000..87c96ec36689 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/unointerfaceproxy.hxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_UNOINTERFACEPROXY_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_UNOINTERFACEPROXY_HXX + +#include "osl/interlck.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "typelib/typedescription.h" +#include "uno/dispatcher.h" +#include "uno/environment.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XInterface; +} } } } + +namespace bridges { namespace cpp_uno { namespace shared { + +class Bridge; + +extern "C" typedef void SAL_CALL FreeUnoInterfaceProxy( + uno_ExtEnvironment * pEnv, void * pProxy); +FreeUnoInterfaceProxy freeUnoInterfaceProxy; + +// private: +extern "C" typedef void SAL_CALL UnoInterfaceProxyDispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException); +UnoInterfaceProxyDispatch unoInterfaceProxyDispatch; + // this function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge + +// private: +extern "C" typedef void SAL_CALL AcquireProxy(uno_Interface *); +AcquireProxy acquireProxy; + +// private: +extern "C" typedef void SAL_CALL ReleaseProxy(uno_Interface *); +ReleaseProxy releaseProxy; + +/** + * A uno proxy wrapping a cpp interface. + */ +class UnoInterfaceProxy: public uno_Interface { +public: + // Interface for Bridge: + + static UnoInterfaceProxy * create( + Bridge * pBridge, com::sun::star::uno::XInterface * pCppI, + typelib_InterfaceTypeDescription * pTypeDescr, + rtl::OUString const & rOId) SAL_THROW(()); + + // Interface for individual CPP--UNO bridges: + + Bridge * getBridge() { return pBridge; } + com::sun::star::uno::XInterface * getCppI() { return pCppI; } + +private: + UnoInterfaceProxy(UnoInterfaceProxy &); // not implemented + void operator =(UnoInterfaceProxy); // not implemented + + UnoInterfaceProxy( + Bridge * pBridge_, com::sun::star::uno::XInterface * pCppI_, + typelib_InterfaceTypeDescription * pTypeDescr_, + rtl::OUString const & rOId_) SAL_THROW(()); + + ~UnoInterfaceProxy(); + + oslInterlockedCount nRef; + Bridge * pBridge; + + // mapping information + com::sun::star::uno::XInterface * pCppI; // wrapped interface + typelib_InterfaceTypeDescription * pTypeDescr; + rtl::OUString oid; + + friend void SAL_CALL freeUnoInterfaceProxy( + uno_ExtEnvironment * pEnv, void * pProxy); + + friend void SAL_CALL unoInterfaceProxyDispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException); + + friend void SAL_CALL acquireProxy(uno_Interface * pUnoI); + + friend void SAL_CALL releaseProxy(uno_Interface * pUnoI); +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx b/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx new file mode 100644 index 000000000000..c21fb7672bc3 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx @@ -0,0 +1,218 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLEFACTORY_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLEFACTORY_HXX + +#include "osl/mutex.hxx" +#include "rtl/alloc.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "typelib/typedescription.hxx" + +#include <boost/unordered_map.hpp> + +/*See: http://people.redhat.com/drepper/selinux-mem.html*/ +#if defined(LINUX) || defined(OPENBSD) || defined(FREEBSD) \ + || defined(NETBSD) || defined(DRAGONFLY) +#define USE_DOUBLE_MMAP +#endif + +namespace bridges { namespace cpp_uno { namespace shared { + +/** Hand out vtable structures for interface type descriptions. + */ +class VtableFactory { +public: + // This structure is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** A vtable slot. + */ + struct Slot; + + /** A raw vtable block. + */ + struct Block { + /** The start of the raw vtable block. + + It points to the start of the allocated memory block, whereas the + vtable pointer typically points some bytes into the block (e.g., + skipping an RTTI pointer, see mapBlockToVtable). Also, the block + contains any generated code snippets, after the vtable itself. + */ + void * start; + +#ifdef USE_DOUBLE_MMAP + /** When seperately mmapping the block for writing and executing + exec points to the same memory as start, except start is used + exclusively for writing and exec for executing + */ + void * exec; + + /** File handle for the underlying anonymous file + */ + int fd; +#endif + + /** The size of the raw vtable block, in bytes. + */ + sal_Size size; + }; + + /** The vtable structure corresponding to an interface type. + */ + struct Vtables { + /** The number of blocks/vtables. + */ + sal_Int32 count; + + /** An array of blocks, representing the multiple vtables of a + (multiple-inheritance) type. + + <p>A block is a raw vtable. It points to the start of the allocated + memory block, whereas the vtable pointer typically points some bytes + into the block (e.g., skipping an RTTI pointer, see + mapBlockToVtable). Also, the block contains any generated code + snippets, after the vtable itself.</p> + */ + Block * blocks; + }; + + VtableFactory(); + + ~VtableFactory(); + + /** Given an interface type description, return its corresponding vtable + structure. + */ + Vtables getVtables(typelib_InterfaceTypeDescription * type); + + // This function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** Given a pointer to a block, turn it into a vtable pointer. + */ + static Slot * mapBlockToVtable(void * block); + +private: + class GuardedBlocks; + friend class GuardedBlocks; + + class BaseOffset; + + VtableFactory(VtableFactory &); // not implemented + void operator =(VtableFactory); // not implemented + + bool createBlock(Block &block, sal_Int32 slotCount) const; + + void freeBlock(Block const & block) const; + + void createVtables( + GuardedBlocks & blocks, BaseOffset const & baseOffset, + typelib_InterfaceTypeDescription * type, bool includePrimary) const; + + // This function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** Calculate the size of a raw vtable block. + + @param slotCount the number of virtual function slots the returned + vtable block shall support (if there are any platform-specific slots, + like an RTTI pointer, or a pointer to a destructor, they are not covered + by slotCount) + @return the size of the raw vtable block, in bytes + */ + static sal_Size getBlockSize(sal_Int32 slotCount); + + // This function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** Initialize a raw vtable block. + + @param block the start address of the raw vtable block + @param slotCount the number of slots + @return a pointer past the last vtable slot + */ + static Slot * initializeBlock(void * block, sal_Int32 slotCount); + + // This function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** Fill the vtable slots corresponding to all local (i.e., not inherited) + functions of a given interface type (and generate any necessary code + snippets for them). + + @param slots on input, points past the vtable slot to be filled with + the last virtual function local to the given type; on output, points to + the vtable slot filled with the first virtual function local to the + given type + @param code points to the start of the area where code snippets can be + generated + @param writetoexecdiff when the same code area is mmaped twice, once for + writing for code-generation, and once for code-execution, then this + records the offset from a writable address to its executable address + @param type the interface type description for which to generate vtable + slots + @param functionOffset the function offset of the first vtable slot + (typically coded into the code snippet for that vtable slot) + @param functionCount the number of vtable slots to fill (the number of + local functions of the given type, passed in so that it need not be + recomputed) + @param vtableOffset the offset of this vtable (needed to adjust the + this pointer, typically coded into the code snippets for all the filled + vtable slots) + @return a pointer to the remaining code snippet area + */ + static unsigned char * addLocalFunctions( + Slot ** slots, unsigned char * code, +#ifdef USE_DOUBLE_MMAP + sal_PtrDiff writetoexecdiff, +#endif + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset); + + // This function is not defined in the generic part, but instead has to be + // defined individually for each CPP--UNO bridge: + /** Flush all the generated code snippets of a vtable, on platforms that + require it. + + @param begin points to the start of the code snippet area + @param end points behind the end of the code snippet area + */ + static void flushCode( + unsigned char const * begin, unsigned char const * end); + + typedef boost::unordered_map< rtl::OUString, Vtables, rtl::OUStringHash > Map; + + osl::Mutex m_mutex; + Map m_map; + + rtl_arena_type * m_arena; +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/shared/vtables.hxx b/bridges/inc/bridges/cpp_uno/shared/vtables.hxx new file mode 100644 index 000000000000..2ea5c7c83121 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/vtables.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLES_HXX +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLES_HXX + +#include "sal/types.h" +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +/** + * Calculate the number of local functions of an interface type. + * + * <p><em>Local</em> functions are those not inherited from any base types. The + * number of <em>functions</em> is potentially larger than the number of + * <em>members</em>, as each read–write attribute member counts as two + * functions.</p> + * + * @param type a non-null pointer to an interface type description, for which + * <code>typelib_typedescription_complete</code> must already have been + * executed + * @return the number of local functions of the given interface type + */ +sal_Int32 getLocalFunctions(typelib_InterfaceTypeDescription const * type); + +/** + * Calculate the number of primary functions of an interface type. + * + * <p>The number of primary functions of an interface is the number of local + * functions of that interface (see <code>getLocalFunctions</code>), plus the + * number of primary functions of that interface's first base type (if it has at + * least one base type).</p> + * + * @param type a pointer to an interface type description; may be null + * @return the number of primary functions of the given interface type, or zero + * if the given interface type is null + */ +sal_Int32 getPrimaryFunctions(typelib_InterfaceTypeDescription * type); + +/** + * Represents a vtable slot of a C++ class. + */ +struct VtableSlot { + /** + * The offset of the vtable. + * + * <p>Multiple-inheritance C++ classes have more than one vtable. The + * offset is logical (<em>not</em> a byte offset), and must be + * non-negative.</p> + */ + sal_Int32 offset; + + /** + * The index within the vtable. + * + * <p>The index is logical (<em>not</em> a byte offset), and must be + * non-negative.</p> + */ + sal_Int32 index; +}; + +/** + * Calculates the vtable slot associated with an interface attribute member. + * + * @param ifcMember a non-null pointer to an interface attribute member + * description + * @return the vtable slot associated with the given interface member + */ +VtableSlot getVtableSlot( + typelib_InterfaceAttributeTypeDescription const * ifcMember); + +/** + * Calculates the vtable slot associated with an interface method member. + * + * @param ifcMember a non-null pointer to an interface method member description + * @return the vtable slot associated with the given interface member + */ +VtableSlot getVtableSlot( + typelib_InterfaceMethodTypeDescription const * ifcMember); + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/bridges/cpp_uno/type_misc.hxx b/bridges/inc/bridges/cpp_uno/type_misc.hxx new file mode 100644 index 000000000000..5fbd0da45cac --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/type_misc.hxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _BRIDGES_CPP_UNO_TYPE_MISC_HXX_ +#define _BRIDGES_CPP_UNO_TYPE_MISC_HXX_ + +#include <sal/types.h> +#include <typelib/typedescription.h> + + +/** Determines whether given type might relate or relates to an interface, + i.e. values of this type are interface or may contain interface(s).<br> + @param pTypeDescr type description of type + @return true if type might relate to an interface, false otherwise +*/ +inline bool cppu_relatesToInterface( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () ) +{ + switch (pTypeDescr->eTypeClass) + { +// case typelib_TypeClass_TYPEDEF: + case typelib_TypeClass_SEQUENCE: + { + switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass) + { + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_UNION: // might relate to interface + case typelib_TypeClass_ANY: // might relate to interface + return true; + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); + bool bRel = cppu_relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + return bRel; + } + default: + return false; + } + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + // ...optimized... to avoid getDescription() calls! + typelib_CompoundTypeDescription * pComp = (typelib_CompoundTypeDescription *)pTypeDescr; + typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs; + for ( sal_Int32 nPos = pComp->nMembers; nPos--; ) + { + switch (pTypes[nPos]->eTypeClass) + { + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_UNION: // might relate to interface + case typelib_TypeClass_ANY: // might relate to interface + return true; +// case typelib_TypeClass_TYPEDEF: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, pTypes[nPos] ); + bool bRel = cppu_relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + if (bRel) + return true; + } + default: + break; + } + } + if (pComp->pBaseTypeDescription) + return cppu_relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription ); + return false; + } + case typelib_TypeClass_UNION: // might relate to interface + case typelib_TypeClass_ANY: // might relate to interface + case typelib_TypeClass_INTERFACE: + return true; + default: + return false; + } +} + +/** Determines whether given type is a cpp simple type, e.g. int, enum.<br> + @param eTypeClass type class of type + @return true if type is a cpp simple type, false otherwise +*/ +inline bool cppu_isSimpleType( typelib_TypeClass eTypeClass ) SAL_THROW( () ) +{ + return (eTypeClass <= typelib_TypeClass_ENUM && + eTypeClass != typelib_TypeClass_STRING && + eTypeClass != typelib_TypeClass_ANY && + eTypeClass != typelib_TypeClass_TYPE); +} +/** Determines whether given type is a cpp simple type, e.g. int, enum.<br> + @param pTypeDescr type description of type + @return true if type is a cpp simple type, false otherwise +*/ +inline bool cppu_isSimpleType( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () ) +{ + return cppu_isSimpleType( pTypeDescr->eTypeClass ); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/makefile.mk b/bridges/inc/makefile.mk new file mode 100644 index 000000000000..de828a78479f --- /dev/null +++ b/bridges/inc/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=.. + +PRJNAME=bridges +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/bridges/inc/pch/precompiled_bridges.cxx b/bridges/inc/pch/precompiled_bridges.cxx new file mode 100644 index 000000000000..05fd24f32377 --- /dev/null +++ b/bridges/inc/pch/precompiled_bridges.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/inc/pch/precompiled_bridges.hxx b/bridges/inc/pch/precompiled_bridges.hxx new file mode 100644 index 000000000000..e0396ac9b835 --- /dev/null +++ b/bridges/inc/pch/precompiled_bridges.hxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:31.967936 + +#ifdef PRECOMPILED_HEADERS +//---MARKER--- +#include "boost/static_assert.hpp" + +#include "com/sun/star/bridge/InvalidProtocolChangeException.hdl" +#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp" +#include "com/sun/star/bridge/ProtocolProperty.hdl" +#include "com/sun/star/bridge/ProtocolProperty.hpp" +#include "com/sun/star/bridge/XBridge.hpp" +#include "com/sun/star/bridge/XBridgeFactory.hpp" +#include "com/sun/star/bridge/XInstanceProvider.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/connection/ConnectionSetupException.hpp" +#include "com/sun/star/connection/NoConnectException.hpp" +#include "com/sun/star/connection/XAcceptor.hpp" +#include "com/sun/star/connection/XConnection.hpp" +#include "com/sun/star/connection/XConnector.hpp" +#include "com/sun/star/frame/XComponentLoader.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/text/XTextDocument.hpp" +#include "com/sun/star/uno/Any.h" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/uno/Exception.hdl" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hdl" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.h" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/Type.h" +#include "com/sun/star/uno/Type.hxx" +#include "com/sun/star/uno/TypeClass.hdl" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hdl" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/XNamingService.hpp" +#include "com/sun/star/uno/genfunc.hxx" + +#include "cppu/macros.hxx" +#include "cppu/unotype.hxx" + +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/servicefactory.hxx" +#include "cppuhelper/weak.hxx" + + +#include "osl/conditn.h" +#include "osl/conditn.hxx" +#include "osl/diagnose.h" +#include "osl/doublecheckedlocking.h" +#include "osl/getglobalmutex.hxx" +#include "osl/interlck.h" +#include "osl/module.h" +#include "osl/module.hxx" +#include "osl/mutex.h" +#include "osl/mutex.hxx" +#include "osl/process.h" +#include "osl/semaphor.h" +#include "osl/thread.h" +#include "osl/thread.hxx" +#include "osl/time.h" + +#include "rtl/alloc.h" +#include "rtl/byteseq.h" +#include "rtl/byteseq.hxx" +#include "rtl/instance.hxx" +#include "rtl/memory.h" +#include "rtl/process.h" +#include "rtl/random.h" +#include "rtl/strbuf.hxx" +#include "rtl/string.h" +#include "rtl/string.hxx" +#include "rtl/unload.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "rtl/uuid.h" + +#include "sal/alloca.h" +#include "sal/config.h" +#include "sal/types.h" + +#include "sys/types.h" + + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "typelib/typedescription.hxx" + +#include "uno/any2.h" +#include "uno/data.h" +#include "uno/dispatcher.h" +#include "uno/environment.h" +#include "uno/environment.hxx" +#include "uno/lbnames.h" +#include "uno/mapping.h" +#include "uno/mapping.hxx" +#include "uno/sequence2.h" +#include "uno/threadpool.h" +//---MARKER--- +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/prj/build.lst b/bridges/prj/build.lst new file mode 100644 index 000000000000..d3d5f6d5ad3d --- /dev/null +++ b/bridges/prj/build.lst @@ -0,0 +1,33 @@ +br bridges : cppuhelper jurt jvmaccess salhelper NULL +br bridges usr1 - all br_mkout NULL +br bridges\inc nmake - all br_inc NULL +br bridges\unotypes nmake - all br_unotypes NULL +br bridges\source\cpp_uno\mingw_intel nmake - w br_gcc3i br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\msvc_win32_intel nmake - w br_msci br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\msvc_win32_x86-64 nmake - w br_mscx br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_intel nmake - u br_gcc3li br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_os2_intel nmake - p br_gcc3os br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_x86-64 nmake - u br_gcc3lx br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_powerpc nmake - u br_gcc3lp br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_aix_powerpc nmake - u br_gcc3ap br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_powerpc64 nmake - u br_gcc3lp_64 br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_mips nmake - u br_gcc3lmips br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_m68k nmake - u br_gcc3lm68k br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_s390 nmake - u br_gcc3l3 br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_s390x nmake - u br_gcc3l3_64 br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_sparc nmake - u br_gcc3ls br_unotypes br_cppuno_shared br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_arm nmake - u br_gcc3lr br_unotypes NULL +br bridges\source\cpp_uno\gcc3_linux_ia64 nmake - u br_gcc3la br_unotypes NULL +br bridges\source\cpp_uno\gcc3_linux_hppa nmake - u br_gcc3lh br_unotypes NULL +br bridges\source\cpp_uno\gcc3_linux_alpha nmake - u br_gcc3ll br_unotypes NULL +br bridges\source\cpp_uno\gcc3_macosx_intel nmake - u br_gcc3macoxi br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_macosx_powerpc nmake - u br_gcc3macoxp br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_ios_arm nmake - u br_gcc3iosr br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\cc50_solaris_sparc nmake - u br_cc50sols br_unotypes br_cppuno_shared br_inc NULL +br bridges\source\cpp_uno\cc5_solaris_sparc64 nmake - u br_cc5sols64 br_unotypes br_cppuno_shared br_inc NULL +br bridges\source\cpp_uno\cc50_solaris_intel nmake - u br_cc50soli br_unotypes br_cppuno_shared br_inc NULL +br bridges\source\cpp_uno\gcc3_solaris_sparc nmake - u br_gcc3sogs br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_solaris_intel nmake - u br_gcc3sogi br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\shared nmake - all br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\jni_uno nmake - all br_jni_uno br_unotypes br_inc NULL +br bridges\source\jni_uno\java\com\sun\star\bridges\jni_uno nmake - all br_jni_uno_java br_unotypes br_inc NULL diff --git a/bridges/prj/d.lst b/bridges/prj/d.lst new file mode 100644 index 000000000000..a8d03e1f2a27 --- /dev/null +++ b/bridges/prj/d.lst @@ -0,0 +1,11 @@ +..\%__SRC%\lib\libjava_uno* %_DEST%\lib\libjava_uno* +..\%__SRC%\bin\java_uno* %_DEST%\bin\java_uno* +..\%__SRC%\class\java_uno*.jar %_DEST%\bin\java_uno*.jar + +..\%__SRC%\bin\msci_uno.* %_DEST%\bin\msci_uno.* +..\%__SRC%\bin\mscx_uno.* %_DEST%\bin\mscx_uno.* +..\%__SRC%\bin\gcc3_uno.dll %_DEST%\bin\gcc3_uno.dll +..\%__SRC%\lib\libgcc2_uno.* %_DEST%\lib\libgcc2_uno.* +..\%__SRC%\lib\libgcc3_uno.* %_DEST%\lib\libgcc3_uno.* +..\%__SRC%\bin\gcc3_uno.* %_DEST%\bin\gcc3_uno.* +..\%__SRC%\lib\libsunpro5_uno.* %_DEST%\lib\libsunpro5_uno.* diff --git a/bridges/source/bridge_exports.map b/bridges/source/bridge_exports.map new file mode 100644 index 000000000000..df39965a2b51 --- /dev/null +++ b/bridges/source/bridge_exports.map @@ -0,0 +1,8 @@ +UDK_3_0_0 { + global: + component_canUnload; + uno_initEnvironment; + uno_ext_getMapping; + local: + *; +}; diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/call.s b/bridges/source/cpp_uno/cc50_solaris_intel/call.s new file mode 100644 index 000000000000..95bf79632031 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/call.s @@ -0,0 +1,248 @@ + .align 4 + .globl privateSnippetExecutorGeneral +privateSnippetExecutorGeneral: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + movl 12(%esp),%eax / 64 bit nRegReturn, lower half + leave + ret + .type privateSnippetExecutorGeneral, @function + .size privateSnippetExecutorGeneral, .-privateSnippetExecutorGeneral + + .align 4 + .globl privateSnippetExecutorVoid +privateSnippetExecutorVoid: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + leave + ret + .type privateSnippetExecutorVoid, @function + .size privateSnippetExecutorVoid, .-privateSnippetExecutorVoid + + .align 4 + .globl privateSnippetExecutorHyper +privateSnippetExecutorHyper: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + movl 12(%esp),%eax / 64 bit nRegReturn, lower half + movl 16(%esp),%edx / 64 bit nRegReturn, upper half + leave + ret + .type privateSnippetExecutorHyper, @function + .size privateSnippetExecutorHyper, .-privateSnippetExecutorHyper + + .align 4 + .globl privateSnippetExecutorFloat +privateSnippetExecutorFloat: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + flds 12(%esp) / 64 bit nRegReturn, lower half + leave + ret + .type privateSnippetExecutorFloat, @function + .size privateSnippetExecutorFloat, .-privateSnippetExecutorFloat + + .align 4 + .globl privateSnippetExecutorDouble +privateSnippetExecutorDouble: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + fldl 12(%esp) / 64 bit nRegReturn + leave + ret + .type privateSnippetExecutorDouble, @function + .size privateSnippetExecutorDouble, .-privateSnippetExecutorDouble + + .align 4 + .globl privateSnippetExecutorStruct +privateSnippetExecutorStruct: + movl %esp,%ecx + pushl %ebp / proper stack frame needed for exception handling + movl %esp,%ebp + andl $0xFFFFFFF8,%esp / align following 64bit arg + subl $0x8,%esp / 64bit nRegReturn + pushl %ecx / 32bit pCallStack + pushl %edx / 32bit nVtableOffset + pushl %eax / 32bit nFunctionIndex + call cpp_vtable_call + movl 12(%esp),%eax / 64 bit nRegReturn, lower half + leave + ret $4 + .type privateSnippetExecutorStruct, @function + .size privateSnippetExecutorStruct, .-privateSnippetExecutorStruct + + .align 4 + .globl callVirtualMethod +callVirtualMethod: + pushl %ebp + movl %esp, %ebp + subl $24, %esp + movl %edx, -4(%ebp) + movl %ecx, -8(%ebp) + movl %eax, -12(%ebp) + movl %esp, -16(%ebp) + movl %ebx, -20(%ebp) + + / set ebx to GOT +.L_GOT_BEGIN_2: + call .L_GOT_END_2 +.L_GOT_END_2: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L_GOT_END_2],%ebx +.callBeginPosition: + movl 28(%ebp), %eax + movl %eax, %edx + dec %edx + shl $2, %edx + add 24(%ebp), %edx +.copyLong: + movl 0(%edx), %ecx + sub $4, %edx + push %ecx + dec %eax + jne .copyLong +.doCall: + movl 8(%ebp), %edx + movl 0(%edx), %edx + movl 12(%ebp), %eax + add $2, %eax + shl $2, %eax + add %eax, %edx + movl 0(%edx), %edx + + call *%edx + +.callVirtualMethodExceptionPosition: + / handle returns + movl 20(%ebp), %ecx + + / byte types + cmp $2, %ecx / typelib_TypeClass_BOOLEAN + je .handleByte + cmp $3, %ecx + je .handleByte / typelib_TypeClass_BYTE + + / half word types + cmp $4, %ecx / typelib_TypeClass_SHORT + je .handleShort + cmp $5, %ecx / typelib_TypeClass_UNSIGNED_SHORT + je .handleShort + + / word types + cmp $6, %ecx / typelib_TypeClass_LONG + je .handleWord + cmp $7, %ecx / typelib_TypeClass_UNSIGNED_LONG + je .handleWord + cmp $1, %ecx / typelib_TypeClass_CHAR (wchar_t) + je .handleWord + cmp $15, %ecx / typelib_TypeClass_ENUM + je .handleWord + + / double word types + cmp $8, %ecx / typelib_TypeClass_HYPER + je .handleDoubleWord + cmp $9, %ecx / typelib_TypeClass_UNSIGNED_HYPER + je .handleDoubleWord + + / float + cmp $10, %ecx / typelib_TypeClass_FLOAT + je .handleFloat + + / double + cmp $11, %ecx / typelib_TypeClass_DOUBLE + je .handleDouble + + / default: return void + jmp .doRestore +.handleByte: + movl 16(%ebp), %ecx + movb %al, 0(%ecx) + jmp .doRestore +.handleShort: + movl 16(%ebp), %ecx + movw %ax, 0(%ecx) + jmp .doRestore +.handleWord: + movl 16(%ebp), %ecx + movl %eax, 0(%ecx) + jmp .doRestore +.handleDoubleWord: + movl 16(%ebp), %ecx + movl %eax, 0(%ecx) + movl %edx, 4(%ecx) + jmp .doRestore +.handleFloat: + movl 16(%ebp), %ecx + fstps 0(%ecx) + jmp .doRestore +.handleDouble: + movl 16(%ebp), %ecx + fstpl 0(%ecx) + jmp .doRestore +.doRestore: + movl -4(%ebp), %edx + movl -8(%ebp), %ecx + movl -12(%ebp), %eax + movl -20(%ebp), %ebx + movl %ebp, %esp + popl %ebp + ret + .type callVirtualMethod, @function + .size callVirtualMethod, .-callVirtualMethod + + .globl callVirtualMethodExceptionHandler +callVirtualMethodExceptionHandler: + movl -4(%ebp), %edx + movl -8(%ebp), %ecx + movl -12(%ebp), %eax + movl -16(%ebp), %esp + movl -20(%ebp), %ebx + call __1cG__CrunMex_rethrow_q6F_v_@PLT + ret + + .type callVirtualMethodExceptionHandler, @function + .size callVirtualMethodExceptionHandler, .-callVirtualMethodExceptionHandler + + + .section .exception_ranges,"aw" + .align 4 + + .4byte .callBeginPosition@rel + .4byte .callVirtualMethodExceptionPosition-.callBeginPosition + .4byte callVirtualMethodExceptionHandler-.callBeginPosition + .zero 8 diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/cc50_solaris_intel.hxx b/bridges/source/cpp_uno/cc50_solaris_intel/cc50_solaris_intel.hxx new file mode 100644 index 000000000000..8e938e2c8105 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/cc50_solaris_intel.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> +#include <rtl/string.hxx> +#include <typeinfo> + +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +// private C50 structures and functions +namespace __Crun +{ + struct static_type_info + { + std::ptrdiff_t m_pClassName; + int m_nSkip1; // must be 0 + void* m_pMagic; // points to some magic data + int m_nMagic[ 4 ]; + int m_nSkip2[2]; // must be 0 + }; + void* ex_alloc(unsigned); + void ex_throw( void*, const static_type_info*, void(*)(void*)); + void* ex_get(); + void ex_rethrow_q(); +} + +namespace __Cimpl +{ + const char* ex_name(); +} + +extern "C" void _ex_register( void*, int ); + +namespace CPPU_CURRENT_NAMESPACE +{ + +//################################################################################################## +//#### exceptions ################################################################################## +//################################################################################################## + +void cc50_solaris_intel_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +void cc50_solaris_intel_fillUnoException( + void*, const char*, + uno_Any*, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/cpp2uno.cxx b/bridges/source/cpp_uno/cc50_solaris_intel/cpp2uno.cxx new file mode 100644 index 000000000000..1a57355f4890 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/cpp2uno.cxx @@ -0,0 +1,530 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "cc50_solaris_intel.hxx" + +using namespace com::sun::star::uno; + +namespace +{ + +//================================================================================================== +void cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void**)pCppStack; + pCppStack += sizeof( void* ); + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[ nPos ] = pUnoArgs[ nPos ] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case no exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::cc50_solaris_intel_raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } +} + + +//================================================================================================== +extern "C" void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack, + sal_Int64 nRegReturn ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, &nRegReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, &nRegReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + // standard XInterface vtable calls + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)&nRegReturn = pCallStack[1]; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, &nRegReturn ); + } + break; + } + default: + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), (XInterface *)pThis ); + } + } +} + +//================================================================================================== +bool isSimpleStruct(typelib_TypeDescriptionReference * type) { + typelib_TypeDescription * td = 0; + TYPELIB_DANGER_GET(&td, type); + OSL_ASSERT(td != 0); + for (typelib_CompoundTypeDescription * ctd + = reinterpret_cast< typelib_CompoundTypeDescription * >(td); + ctd != 0; ctd = ctd->pBaseTypeDescription) + { + OSL_ASSERT(ctd->aBase.eTypeClass == typelib_TypeClass_STRUCT); + for (sal_Int32 i = 0; i < ctd->nMembers; ++i) { + typelib_TypeClass c = ctd->ppTypeRefs[i]->eTypeClass; + switch (c) { + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + return false; + case typelib_TypeClass_STRUCT: + if (!isSimpleStruct(ctd->ppTypeRefs[i])) { + return false; + } + break; + default: + OSL_ASSERT( + c <= typelib_TypeClass_DOUBLE + || c == typelib_TypeClass_ENUM); + break; + } + } + } + TYPELIB_DANGER_RELEASE(td); + return true; +} + +extern "C" void privateSnippetExecutorGeneral(); +extern "C" void privateSnippetExecutorVoid(); +extern "C" void privateSnippetExecutorHyper(); +extern "C" void privateSnippetExecutorFloat(); +extern "C" void privateSnippetExecutorDouble(); +extern "C" void privateSnippetExecutorStruct(); +extern "C" typedef void (*PrivateSnippetExecutor)(); + +int const codeSnippetSize = 16; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + typelib_TypeDescriptionReference * returnType) +{ + typelib_TypeClass c = returnType == 0 + ? typelib_TypeClass_VOID : returnType->eTypeClass; + if (returnType != 0 && !bridges::cpp_uno::shared::isSimpleType(c)) { + functionIndex |= 0x80000000; + } + PrivateSnippetExecutor exec; + switch (c) { + case typelib_TypeClass_VOID: + exec = privateSnippetExecutorVoid; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + exec = privateSnippetExecutorHyper; + break; + case typelib_TypeClass_FLOAT: + exec = privateSnippetExecutorFloat; + break; + case typelib_TypeClass_DOUBLE: + exec = privateSnippetExecutorDouble; + break; + case typelib_TypeClass_STRUCT: + OSL_ASSERT(returnType != 0); + // For "simple" (more-or-less POD, but not exactly) structs, the caller + // pops the pointer to the return value off the stack, as documented in + // the Intel SYSV ABI; for other structs (which includes STRING, TYPE, + // ANY, sequences, and interfaces, btw.), the callee pops the pointer to + // the return value off the stack: + exec = isSimpleStruct(returnType) + ? privateSnippetExecutorStruct : privateSnippetExecutorGeneral; + break; + default: + exec = privateSnippetExecutorGeneral; + break; + } + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov function_index, %eax: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov vtable_offset, %edx: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // jmp privateSnippetExecutor: + *p++ = 0xE9; +#pragma disable_warn + void * e = reinterpret_cast< void * >(exec); +#pragma enable_warn + *reinterpret_cast< sal_Int32 * >(p) + = static_cast< unsigned char * >(e) - p - sizeof (sal_Int32); + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block) + 2; + slots[-3].fn = 0; // RTTI + slots[-2].fn = 0; // null + slots[-1].fn = 0; // destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset, 0); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/except.cxx b/bridges/source/cpp_uno/cc50_solaris_intel/except.cxx new file mode 100644 index 000000000000..6a9b923a4e26 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/except.cxx @@ -0,0 +1,454 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <cstddef> +#include <dlfcn.h> +#include <new.h> +#include <typeinfo> +#include <list> +#include <map> +#include <rtl/alloc.h> +#include <osl/diagnose.h> + +#include <rtl/strbuf.hxx> +#include <typelib/typedescription.hxx> +#include <com/sun/star/uno/Any.hxx> + +#include "bridges/cpp_uno/shared/arraypointer.hxx" + +#include "cc50_solaris_intel.hxx" + +#include <hash.cxx> + +// need a += operator for OString and sal_Char +using ::rtl::OUString; +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OUStringToOString; +using ::rtl::OStringToOUString; +{ + inline OString& operator+=( OString& rString, sal_Char cAdd ) + { + sal_Char add[2]; + add[0] = cAdd; + add[1] = 0; + return rString += add; + } +} + +using namespace std; +using namespace osl; +using namespace com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + +static OString toUNOname( const OString & rRTTIname ) +{ + OString aRet; + + const sal_Char* pRTTI = rRTTIname.getStr(); + const sal_Char* pOrg = pRTTI; + const sal_Char* pLast = pRTTI; + + while( 1 ) + { + if( *pRTTI == ':' || ! *pRTTI ) + { + if( aRet.getLength() ) + aRet += "."; + aRet += rRTTIname.copy( pLast - pOrg, pRTTI - pLast ); + while( *pRTTI == ':' ) + pRTTI++; + pLast = pRTTI; + if( ! *pRTTI ) + break; + } + else + pRTTI++; + } + + return aRet; +} +//================================================================================================== +static OString toRTTIname( const OString & rUNOname ) +{ + OStringBuffer aRet( rUNOname.getLength()*2 ); + + sal_Int32 nIndex = 0; + do + { + if( nIndex > 0 ) + aRet.append( "::" ); + aRet.append( rUNOname.getToken( 0, '.', nIndex ) ); + } while( nIndex != -1 ); + + return aRet.makeStringAndClear(); +} +//================================================================================================== + +static OString toRTTImangledname( const OString & rRTTIname ) +{ + if( ! rRTTIname.getLength() ) + return OString(); + + OStringBuffer aRet( rRTTIname.getLength()*2 ); + + aRet.append( "__1n" ); + sal_Int32 nIndex = 0; + do + { + OString aToken( rRTTIname.getToken( 0, ':', nIndex ) ); + int nBytes = aToken.getLength(); + if( nBytes ) + { + if( nBytes > 25 ) + { + aRet.append( (sal_Char)( nBytes/26 + 'a' ) ); + aRet.append( (sal_Char)( nBytes%26 + 'A' ) ); + } + else + aRet.append( (sal_Char)( nBytes + 'A' ) ); + for (sal_Int32 i = 0; i < aToken.getLength(); ++i) { + char c = aToken[i]; + if (c == 'Q') { + aRet.append("QdD"); + } else { + aRet.append(c); + } + } + } + } while( nIndex != -1 ); + + aRet.append( '_' ); + + return aRet.makeStringAndClear(); +} + +//################################################################################################## +//#### RTTI simulation ############################################################################# +//################################################################################################## + +class RTTIHolder +{ + std::map< OString, void* > aAllRTTI; +public: + ~RTTIHolder(); + + void* getRTTI( const OString& rTypename ); + void* getRTTI_UnoName( const OString& rUnoTypename ) + { return getRTTI( toRTTIname( rUnoTypename ) ); } + + void* insertRTTI( const OString& rTypename ); + void* insertRTTI_UnoName( const OString& rTypename ) + { return insertRTTI( toRTTIname( rTypename ) ); } + void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr ); +}; + +RTTIHolder::~RTTIHolder() +{ + for ( std::map< OString, void* >::const_iterator iPos( aAllRTTI.begin() ); + iPos != aAllRTTI.end(); ++iPos ) + { + delete[] static_cast< char * >(iPos->second); + } +} + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif + +void* RTTIHolder::getRTTI( const OString& rTypename ) +{ + std::map< OString, void* >::iterator element; + + element = aAllRTTI.find( rTypename ); + if( element != aAllRTTI.end() ) + return (*element).second; + + // create rtti structure + element = aAllRTTI.find( rTypename ); + if( element != aAllRTTI.end() ) + return (*element).second; + + return NULL; +} + +static long nMagicId = 1; + +void* RTTIHolder::insertRTTI( const OString& rTypename ) +{ + OString aMangledName( toRTTImangledname( rTypename ) ); + NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); + + + // rSuperTypename MUST exist !!! + std::size_t const RTTI_SIZE = 19; // 14??? + void** pRTTI = reinterpret_cast< void ** >( + new char[RTTI_SIZE * sizeof (void *) + strlen(rTypename.getStr()) + 1]); + pRTTI[ 0 ] = reinterpret_cast< void * >(RTTI_SIZE * sizeof (void *)); + pRTTI[ 1 ] = NULL; + pRTTI[ 2 ] = (void*)(7*sizeof(void*)); + pRTTI[ 3 ] = (void*)aHash.getHash()[0]; + pRTTI[ 4 ] = (void*)aHash.getHash()[1]; + pRTTI[ 5 ] = (void*)aHash.getHash()[2]; + pRTTI[ 6 ] = (void*)aHash.getHash()[3]; + pRTTI[ 7 ] = NULL; + pRTTI[ 8 ] = NULL; + + pRTTI[ 9 ] = pRTTI[ 3 ]; + pRTTI[ 10 ] = pRTTI[ 4 ]; + pRTTI[ 11 ] = pRTTI[ 5 ]; + pRTTI[ 12 ] = pRTTI[ 6 ]; + pRTTI[ 13 ] = (void*)0x80000000; + strcpy(reinterpret_cast< char * >(pRTTI + RTTI_SIZE), rTypename.getStr()); + + aAllRTTI[ rTypename ] = (void*)pRTTI; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "generating base RTTI for type %s:\n" + " mangled: %s\n" + " hash: %.8x %.8x %.8x %.8x\n", + rTypename.getStr(), + aMangledName.getStr(), + pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] + ); +#endif + return pRTTI; +} + +void* RTTIHolder::generateRTTI( typelib_CompoundTypeDescription * pCompTypeDescr ) +{ + OString aUNOCompTypeName( OUStringToOString( pCompTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + OString aRTTICompTypeName( toRTTIname( aUNOCompTypeName ) ); + + void* pHaveRTTI = getRTTI( aRTTICompTypeName ); + if( pHaveRTTI ) + return pHaveRTTI; + + if( ! pCompTypeDescr->pBaseTypeDescription ) + // this is a base type + return insertRTTI( aRTTICompTypeName ); + + // get base class RTTI + void* pSuperRTTI = generateRTTI( pCompTypeDescr->pBaseTypeDescription ); + OSL_ENSURE( pSuperRTTI, "could not generate RTTI for supertype !" ); + + // find out the size to allocate for RTTI + void** pInherit = (void**)((sal_uInt32)pSuperRTTI + ((sal_uInt32*)pSuperRTTI)[2] + 8); + int nInherit; + for( nInherit = 1; pInherit[ nInherit*5-1 ] != (void*)0x80000000; nInherit++ ) + ; + + OString aMangledName( toRTTImangledname( aRTTICompTypeName ) ); + NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); + + std::size_t const rttiSize = 14 + nInherit * 5; + void** pRTTI = reinterpret_cast< void ** >( + new char[ + rttiSize * sizeof (void *) + + strlen(aRTTICompTypeName.getStr()) + 1]); + pRTTI[ 0 ] = reinterpret_cast< void * >(rttiSize * sizeof (void *)); + pRTTI[ 1 ] = NULL; + pRTTI[ 2 ] = (void*)(7*sizeof(void*)); + pRTTI[ 3 ] = (void*)aHash.getHash()[0]; + pRTTI[ 4 ] = (void*)aHash.getHash()[1]; + pRTTI[ 5 ] = (void*)aHash.getHash()[2]; + pRTTI[ 6 ] = (void*)aHash.getHash()[3]; + pRTTI[ 7 ] = NULL; + pRTTI[ 8 ] = NULL; + + memcpy( pRTTI+9, pInherit, 4*nInherit*5 ); + pRTTI[ 8 +nInherit*5 ] = NULL; + pRTTI[ 9 +nInherit*5 ] = pRTTI[ 3 ]; + pRTTI[ 10+nInherit*5 ] = pRTTI[ 4 ]; + pRTTI[ 11+nInherit*5 ] = pRTTI[ 5 ]; + pRTTI[ 12+nInherit*5 ] = pRTTI[ 6 ]; + pRTTI[ 13+nInherit*5 ] = (void*)0x80000000; + strcpy( + reinterpret_cast< char * >(pRTTI + rttiSize), + aRTTICompTypeName.getStr()); + + aAllRTTI[ aRTTICompTypeName ] = (void*)pRTTI; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "generating struct RTTI for type %s:\n" + " mangled: %s\n" + " hash: %.8x %.8x %.8X %.8x\n", + aRTTICompTypeName.getStr(), + aMangledName.getStr(), + pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] + ); +#endif + + return pRTTI; +} + +//__________________________________________________________________________________________________ + +static void deleteException( + void* pExc, unsigned char* thunk, typelib_TypeDescription* pType ) +{ + uno_destructData( + pExc, pType, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + typelib_typedescription_release( pType ); + delete[] thunk; +} + +//__________________________________________________________________________________________________ + +//################################################################################################## +//#### exported #################################################################################### +//################################################################################################## + +void cc50_solaris_intel_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + bridges::cpp_uno::shared::ArrayPointer< unsigned char > thunkPtr( + new unsigned char[24]); + typelib_TypeDescription * pTypeDescr = 0; + // will be released by deleteException + typelib_typedescriptionreference_getDescription( &pTypeDescr, pUnoExc->pType ); + + void* pRTTI; + { + static ::osl::Mutex aMutex; + ::osl::Guard< ::osl::Mutex > guard( aMutex ); + + static RTTIHolder * s_pRTTI = 0; + if (! s_pRTTI) + { +#ifdef LEAK_STATIC_DATA + s_pRTTI = new RTTIHolder(); +#else + static RTTIHolder s_aRTTI; + s_pRTTI = &s_aRTTI; +#endif + } + + pRTTI = s_pRTTI->generateRTTI( (typelib_CompoundTypeDescription *)pTypeDescr ); + } + + // a must be + OSL_ENSURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" ); + + void * pCppExc = __Crun::ex_alloc( pTypeDescr->nSize ); + uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + uno_any_destruct( pUnoExc, 0 ); + + unsigned char * thunk = thunkPtr.release(); + // movl %esp, %ecx: + thunk[0] = 0x8B; + thunk[1] = 0xCC; + // pushl pTypeDescr: + thunk[2] = 0x68; + *reinterpret_cast< void ** >(thunk + 3) = pTypeDescr; + // pushl thunk: + thunk[7] = 0x68; + *reinterpret_cast< void ** >(thunk + 8) = thunk; + // pushl 4(%ecx): + thunk[12] = 0xFF; + thunk[13] = 0x71; + thunk[14] = 0x04; + // call deleteException: + thunk[15] = 0xE8; +#pragma disable_warn + void * d = reinterpret_cast< void * >(deleteException); +#pragma enable_warn + *reinterpret_cast< std::ptrdiff_t * >(thunk + 16) = + static_cast< unsigned char * >(d) - (thunk + 20); + // addl $12, %esp: + thunk[20] = 0x83; + thunk[21] = 0xC4; + thunk[22] = 0x0C; + // ret: + thunk[23] = 0xC3; + +#pragma disable_warn + void (* f)(void *) = reinterpret_cast< void (*)(void *) >(thunk); +#pragma enable_warn + __Crun::ex_throw(pCppExc, (const __Crun::static_type_info*)pRTTI, f); +} + +void cc50_solaris_intel_fillUnoException( + void* pCppExc, + const char* pInfo, + uno_Any* pUnoExc, + uno_Mapping * pCpp2Uno ) +{ + OSL_ASSERT( pInfo != 0 ); + OString uno_name( toUNOname( pInfo ) ); + OUString aName( OStringToOUString( + uno_name, RTL_TEXTENCODING_ASCII_US ) ); + typelib_TypeDescription * pExcTypeDescr = 0; + typelib_typedescription_getByName( &pExcTypeDescr, aName.pData ); + + if (pExcTypeDescr == 0) // the thing that should not be + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "exception type not found: ") ) + aName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( + pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( + aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "> c++ exception occurred: %s\n", + ::rtl::OUStringToOString( + pExcTypeDescr->pTypeName, + RTL_TEXTENCODING_ASCII_US ).getStr() ); +#endif + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, pCppExc, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/hash.cxx b/bridges/source/cpp_uno/cc50_solaris_intel/hash.cxx new file mode 100644 index 000000000000..c1c2c2dc8eb6 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/hash.cxx @@ -0,0 +1,264 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#ifndef TEST +#include <sal/types.h> +#else +typedef unsigned int sal_uInt32; +#endif + +#include <string.h> + +/* + * build a hash for a character buffer using the NIST algorithm + */ + +class NIST_Hash +{ + + // helper functions + sal_uInt32 f1( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return z ^ ( x & ( y ^ z ) ); + } + + sal_uInt32 f2( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return x ^ y ^ z; + } + + sal_uInt32 f3( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return ( x & y ) + ( z & ( x ^ y ) ); + } + + sal_uInt32 rotl( sal_uInt32 nValue, sal_uInt32 nBits ) + { + return ( nValue << nBits ) | ( nValue >> (32-nBits) ); + } + + sal_uInt32 expand_nostore( sal_uInt32 index ) + { + return data[index&15] ^ data[(index-14)&15] ^ data[(index-8)&15] ^ data[(index-3)&15]; + } + + sal_uInt32 expand_store( sal_uInt32 index ) + { + return data[index&15] ^= data[(index-14)&15] ^ data[(index-8)&15] ^ data[(index-3)&15]; + } + + void subRound( sal_uInt32 a, sal_uInt32& b, sal_uInt32 c, sal_uInt32 d, sal_uInt32& e, sal_uInt32 constant, sal_uInt32 datum, sal_uInt32 nFunction ) + { + e += rotl(a,5); + switch( nFunction ) + { + case 1: e += f1( b, c, d );break; + case 2: + case 4: e += f2( b, c, d );break; + case 3: e += f3( b, c, d );break; + } + e += constant + datum; + b = rotl( b, 30 ); + } + + void transform(); + void final(); + + // data members + sal_uInt32 data[16]; + sal_uInt32 hashdata[5]; +public: + NIST_Hash( const char* pString, sal_uInt32 nLen ); + + sal_uInt32 *getHash() { return hashdata; } +}; + +void NIST_Hash::transform() +{ + // constants + const sal_uInt32 K2 = 0x5A827999; + const sal_uInt32 K3 = 0x6ED9EBA1; + const sal_uInt32 K5 = 0x8F1BBCDC; + const sal_uInt32 K10 = 0xCA62C1D6; + + sal_uInt32 a, b, c, d, e; + a = hashdata[0]; + b = hashdata[1]; + c = hashdata[2]; + d = hashdata[3]; + e = hashdata[4]; + + subRound( a, b, c, d, e, K2, data[ 0], 1 ); + subRound( e, a, b, c, d, K2, data[ 1], 1 ); + subRound( d, e, a, b, c, K2, data[ 2], 1 ); + subRound( c, d, e, a, b, K2, data[ 3], 1 ); + subRound( b, c, d, e, a, K2, data[ 4], 1 ); + subRound( a, b, c, d, e, K2, data[ 5], 1 ); + subRound( e, a, b, c, d, K2, data[ 6], 1 ); + subRound( d, e, a, b, c, K2, data[ 7], 1 ); + subRound( c, d, e, a, b, K2, data[ 8], 1 ); + subRound( b, c, d, e, a, K2, data[ 9], 1 ); + subRound( a, b, c, d, e, K2, data[10], 1 ); + subRound( e, a, b, c, d, K2, data[11], 1 ); + subRound( d, e, a, b, c, K2, data[12], 1 ); + subRound( c, d, e, a, b, K2, data[13], 1 ); + subRound( b, c, d, e, a, K2, data[14], 1 ); + subRound( a, b, c, d, e, K2, data[15], 1 ); + subRound( e, a, b, c, d, K2, expand_store( 16 ), 1 ); + subRound( d, e, a, b, c, K2, expand_store( 17 ), 1 ); + subRound( c, d, e, a, b, K2, expand_store( 18 ), 1 ); + subRound( b, c, d, e, a, K2, expand_store( 19 ), 1 ); + + subRound( a, b, c, d, e, K3, expand_store( 20 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 21 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 22 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 23 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 24 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 25 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 26 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 27 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 28 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 29 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 30 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 31 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 32 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 33 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 34 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 35 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 36 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 37 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 38 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 39 ), 2 ); + + subRound( a, b, c, d, e, K5, expand_store( 40 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 41 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 42 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 43 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 44 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 45 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 46 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 47 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 48 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 49 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 50 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 51 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 52 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 53 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 54 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 55 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 56 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 57 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 58 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 59 ), 3 ); + + subRound( a, b, c, d, e, K10, expand_store( 60 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 61 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 62 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 63 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 64 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 65 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 66 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 67 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 68 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 69 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 70 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 71 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 72 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 73 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 74 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 75 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 76 ), 4 ); + subRound( d, e, a, b, c, K10, expand_nostore( 77 ), 4 ); + subRound( c, d, e, a, b, K10, expand_nostore( 78 ), 4 ); + subRound( b, c, d, e, a, K10, expand_nostore( 79 ), 4 ); + + hashdata[0] += a; + hashdata[1] += b; + hashdata[2] += c; + hashdata[3] += d; + hashdata[4] += e; +} + +#define BLOCKSIZE sizeof( data ) + +NIST_Hash::NIST_Hash( const char* pString, sal_uInt32 nLen ) +{ + hashdata[0] = 0x67452301; + hashdata[1] = 0xefcdab89; + hashdata[2] = 0x98badcfe; + hashdata[3] = 0x10325476; + hashdata[4] = 0xc3d2e1f0; + + sal_uInt32 nBytes = nLen; + + while( nLen >= sizeof( data ) ) + { + memcpy( data, pString, sizeof( data ) ); + pString += sizeof( data ); + nLen -= sizeof( data ); + transform(); + } + memcpy( data, pString, nLen ); + ((char*)data)[nLen++] = 0x80; + if( nLen > sizeof( data ) - 8 ) + { + memset( ((char*)data)+nLen, 0, sizeof( data ) - nLen ); + transform(); + memset( data, 0, sizeof( data ) - 8 ); + } + else + memset( ((char*)data)+nLen, 0, sizeof( data ) - 8 - nLen ); + data[14] = 0; + data[15] = nBytes << 3; + transform(); +} + +#ifdef TEST +#include <stdio.h> +int main( int argc, const char** argv ) +{ + const char* pHash = argc < 2 ? argv[0] : argv[1]; + + NIST_Hash aHash( pHash, strlen( pHash ) ); + sal_uInt32* pBits = aHash.getHash(); + + printf( "text : %s\n" + "bits : 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", + pHash, + pBits[0], pBits[1], pBits[2],pBits[3],pBits[4] + ); + return 0; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/makefile.mk b/bridges/source/cpp_uno/cc50_solaris_intel/makefile.mk new file mode 100644 index 000000000000..e3d10f829187 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/makefile.mk @@ -0,0 +1,75 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=sunpro5_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +# disable check for PIC code as it would complain about +# hand coded assembler +CHECKFORPIC= + +.IF "$(COM)$(CPU)" == "C50I" || "$(COM)$(CPU)" == "C52I" + +CFLAGS += -O5 -xO5 + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/except.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB= i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH= URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + CC -c -o $(SLO)$/$(@:b).o $< && touch $@ + diff --git a/bridges/source/cpp_uno/cc50_solaris_intel/uno2cpp.cxx b/bridges/source/cpp_uno/cc50_solaris_intel/uno2cpp.cxx new file mode 100644 index 000000000000..287ca5deadd7 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/uno2cpp.cxx @@ -0,0 +1,422 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "cc50_solaris_intel.hxx" + +using namespace com::sun::star::uno; + +using ::rtl::OUString; + +namespace +{ + +extern "C" { + void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs + ); +} + +//================================================================================================== +static inline void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + void * pReturnSpace = 0; + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + const int nMaxParams = 32; + // args + void * args_buffer[3 * nMaxParams]; + void ** pCppArgs = (void **)(nParams > nMaxParams ? rtl_allocateMemory( 3 * sizeof(void *) * nParams ) : args_buffer); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + const int nTempBufferSize = 256; + sal_Int32 nTempBufferPos = 0; + long params_buffer[nTempBufferSize]; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + pCppArgs[ nPos ] = pCppStack; + uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + if (pParamTypeDescr->nSize > (sizeof(long) * (nTempBufferSize - nTempBufferPos))) + { + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = rtl_allocateMemory( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos | 0x80000000; // default constructed for cpp call + } + else + { + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = (params_buffer + nTempBufferPos), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + nTempBufferPos += (pParamTypeDescr->nSize / sizeof(long)) +1; + } + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + if (pParamTypeDescr->nSize > (sizeof(long)*(nTempBufferSize - nTempBufferPos))) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = rtl_allocateMemory( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + pTempIndizes[nTempIndizes] = nPos | 0x80000000; // has to be reconverted + } + else + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = (params_buffer + nTempBufferPos), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + nTempBufferPos += (pParamTypeDescr->nSize / sizeof(long)) +1; + } + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); + if( nStackLongs & 1 ) + // stack has to be 8 byte aligned + nStackLongs++; + + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, + pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, + nStackLongs + ); + + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + sal_Bool bAllocated = (nIndex & 0x80000000) != 0; + nIndex &= 0x7fffffff; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + + if (bAllocated) + rtl_freeMemory( pCppArgs[nIndex] ); + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( + pCppReturn, pReturnTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + } + } + catch( ... ) + { + void* pExc = __Crun::ex_get(); + const char* pName = __Cimpl::ex_name(); + + // get exception + CPPU_CURRENT_NAMESPACE::cc50_solaris_intel_fillUnoException( + pExc, pName, *ppUnoExc, + pThis->getBridge()->getCpp2Uno()); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + sal_Bool bAllocated = (nIndex & 0x80000000) != 0; + nIndex &= 0x7fffffff; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( + pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + if (bAllocated) + rtl_freeMemory( pCppArgs[nIndex] ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + + if (pCppArgs != (void **)args_buffer) + rtl_freeMemory( pCppArgs ); + if (pReturnSpace) + rtl_freeMemory( pReturnSpace ); +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/call.s b/bridges/source/cpp_uno/cc50_solaris_sparc/call.s new file mode 100644 index 000000000000..be4027fda070 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/call.s @@ -0,0 +1,199 @@ +.global privateSnippetExecutor +.type privateSnippetExecutor,2 +privateSnippetExecutor: + ! save %sp, -96, %sp already done in code snippet + st %i0, [%fp+68] + st %i1, [%fp+72] + st %i2, [%fp+76] + st %i3, [%fp+80] + st %i4, [%fp+84] + st %i5, [%fp+88] + ! %o0: functionIndex, stored by code snippet + ! %o1: vtableOffset, stored by code snippet + call cpp_vtable_call + add %fp, 68, %o2 +.privateSnippetExecutorExceptionPosition: + subcc %o0, 11, %g0 + be .double + subcc %o0, 10, %g0 + be .float + ld [%fp+72], %i0 + ld [%fp+76], %i1 + ret + restore +.double: + ldd [%fp+72], %f0 + ret + restore +.float: + ld [%fp+72], %f0 + ret + restore +.size privateSnippetExecutor,(.-privateSnippetExecutor) +.align 8 + + +.global callVirtualMethod +.type callVirtualMethod,2 +callVirtualMethod: + ! allocate FIRST stack to have own local registers + sethi %hi(-96), %g1 + or %g1, %lo(-96), %g1 + subcc %g1, %o5, %g1 + subcc %g1, %o5, %g1 + subcc %g1, %o5, %g1 + subcc %g1, %o5, %g1 + save %sp, %g1, %sp + ! copy stack longs if necessary + subcc %i5, 6, %l5 + ble .copyRegisters + nop + + ! prepare source location + add %i4, 24, %l4 + + ! prepare real stack + add %sp, 92, %l3 + +.copyLong: + ld [%l4+0], %l0 + st %l0, [%l3] + add %l4, 4, %l4 + add %l3, 4, %l3 + deccc %l5 + bne .copyLong + nop +.copyRegisters: + mov %i5, %l5 + mov %i4, %l4 + + ld [%l4], %o0 + add %l4, 4, %l4 + deccc %l5 + ble .doCall + + ld [%l4], %o1 + add %l4, 4, %l4 + deccc %l5 + ble .doCall + + ld [%l4], %o2 + add %l4, 4, %l4 + deccc %l5 + ble .doCall + + ld [%l4], %o3 + add %l4, 4, %l4 + deccc %l5 + ble .doCall + + ld [%l4], %o4 + add %l4, 4, %l4 + deccc %l5 + ble .doCall + + ld [%l4], %o5 + add %l4, 4, %l4 + + ! prepare complex return pointer + st %i2, [%sp+64] +.doCall: + ! get virtual table entry + mov %i1, %l1 + add %l1, 2, %l1 + sll %l1, 2, %l1 + ld [%i0], %l3 + add %l3, %l1, %l1 + ld [%l1], %l0 + jmpl %l0,%o7 + nop +.callVirtualMethodExceptionPosition: + ! handle returns + + !byte types + subcc %i3, 2, %l3 ! typelib_TypeClass_BOOLEAN + be .handleByte + subcc %i3, 3, %l3 ! typelib_TypeClass_BYTE + be .handleByte + + ! half word types + subcc %i3, 4, %l3 ! typelib_TypeClass_SHORT + be .handleShort + subcc %i3, 5, %l3 ! typelib_TypeClass_UNSIGNED_SHORT + be .handleShort + subcc %i3, 1, %l3 ! typelib_TypeClass_CHAR (sal_Unicode==sal_uInt16) + be .handleShort + + ! word types + subcc %i3, 6, %l3 ! typelib_TypeClass_LONG + be .handleWord + subcc %i3, 7, %l3 ! typelib_TypeClass_UNSIGNED_LONG + be .handleWord + subcc %i3, 15, %l3 ! typelib_TypeClass_ENUM + be .handleWord + + ! double word types + subcc %i3, 8, %l3 ! typelib_TypeClass_HYPER + be .handleDoubleWord + subcc %i3, 9, %l3 ! typelib_TypeClass_UNSIGNED_HYPER + be .handleDoubleWord + + ! float + subcc %i3, 10, %l3 ! typelib_TypeClass_FLOAT + be .handleFloat + + ! double + subcc %i3, 11, %l3 ! typelib_TypeClass_DOUBLE + be .handleDouble + + ! default: return void + nop ! empty prefetch + ba .doRestore + nop +.handleByte: + stb %o0, [%i2] + ba .doRestore + nop +.handleShort: + sth %o0, [%i2] + ba .doRestore + nop +.handleWord: + st %o0, [%i2] + ba .doRestore + nop +.handleDoubleWord: + st %o0, [%i2] + st %o1, [%i2+4] + ba .doRestore + nop +.handleFloat: + st %f0, [%i2] + ba .doRestore + nop +.handleDouble: + std %f0, [%fp-8] + ldd [%fp-8], %o0 + st %o0, [%i2] + st %o1, [%i2+4] + ba .doRestore + nop +.doRestore: + ret + restore ! stack frame for own locals +.size callVirtualMethod,(.-callVirtualMethod) +.align 8 + +.rethrow_handler: + call __1cG__CrunMex_rethrow_q6F_v_ + nop + +.section ".exception_ranges",#alloc +.word %r_disp32(.privateSnippetExecutorExceptionPosition) +.word 0 +.word .rethrow_handler-.privateSnippetExecutorExceptionPosition +.word 0,0 +.word %r_disp32(.callVirtualMethodExceptionPosition) +.word 0 +.word .rethrow_handler-.callVirtualMethodExceptionPosition +.word 0,0 diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/cc50_solaris_sparc.hxx b/bridges/source/cpp_uno/cc50_solaris_sparc/cc50_solaris_sparc.hxx new file mode 100644 index 000000000000..06667e4a366c --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/cc50_solaris_sparc.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> +#include <rtl/string.hxx> +#include <typeinfo> + +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +// private C50 structures and functions +namespace __Crun +{ + struct static_type_info + { + std::ptrdiff_t m_pClassName; + int m_nSkip1; // must be 0 + void* m_pMagic; // points to some magic data + int m_nMagic[ 4 ]; + int m_nSkip2[2]; // must be 0 + }; + void* ex_alloc(unsigned); + void ex_throw( void*, const static_type_info*, void(*)(void*)); + void* ex_get(); + void ex_rethrow_q() throw(); +} + +namespace __Cimpl +{ + const char* ex_name(); +} + +extern "C" void _ex_register( void*, int ); + +namespace CPPU_CURRENT_NAMESPACE +{ + +inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType ) +{ + switch( pType->nSize ) + { + case 1: return pIn + 3; + case 2: return pIn + 2; + case 3: return pIn + 1; + // Huh ? perhaps a char[3] ? Though that would be a pointer + // well, we have it anyway for symmetry + } + return pIn; +} + +//################################################################################################## +//#### exceptions ################################################################################## +//################################################################################################## + +void cc50_solaris_sparc_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +void cc50_solaris_sparc_fillUnoException( + void*, const char*, + uno_Any*, uno_Mapping * pCpp2Uno ); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/cpp2uno.cxx b/bridges/source/cpp_uno/cc50_solaris_sparc/cpp2uno.cxx new file mode 100644 index 000000000000..6076f66093d1 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/cpp2uno.cxx @@ -0,0 +1,517 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "cc50_solaris_sparc.hxx" +#include "flushcode.hxx" + +using namespace com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: [return ptr], this, params + char * pCppStack = (char *)pCallStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *pCallStack; + pCppStack += sizeof( void* ); + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[ nPos ] = pUnoArgs[ nPos ] = + CPPU_CURRENT_NAMESPACE::adjustPointer( + pCppStack, pParamTypeDescr ); + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case no exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[1]; + } + else + { + pThis = pCallStack[0]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + // standard XInterface vtable calls + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[0] ), + &pInterface, pTD, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + } + + return eRet; +} + +} + +//================================================================================================== +extern "C" int cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack ) +{ + sal_Int64 nRegReturn; + typelib_TypeClass aType = cpp_mediate( + nFunctionIndex, nVtableOffset, pCallStack, &nRegReturn ); + OSL_ASSERT( sizeof(void *) == sizeof(sal_Int32) ); + switch( aType ) + { + // move return value into register space + // (will be loaded by machine code snippet) + // Use pCallStack[1/2] instead of pCallStack[0/1], because the former is + // properly dword aligned: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pCallStack[1] = (void*)*(char*)&nRegReturn; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pCallStack[1] = (void*)*(short*)&nRegReturn; + break; + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + // move long to %i1 + pCallStack[2] = ((void **)&nRegReturn)[ 1 ]; + case typelib_TypeClass_FLOAT: + default: + // move long to %i0 + pCallStack[1] = ((void **)&nRegReturn)[ 0 ]; + break; + } + return aType; +} + +//================================================================================================== +namespace { + +extern "C" void privateSnippetExecutor(); + +int const codeSnippetSize = 7 * 4; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) +{ + sal_uInt32 index = functionIndex; + if (!simpleRetType) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + OSL_ASSERT(sizeof (unsigned int) == 4); + // save %sp, -96, %sp ! 92 byte minimal stack frame, + 4 byte dword align: + *p++ = 0x9DE3BFA0; + // sethi %hi(privateSnippetExecutor), %l0: + *p++ = 0x21000000 + | (reinterpret_cast< unsigned int >(privateSnippetExecutor) >> 10); + // sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // sethi %hi(vtableOffset), %o1: + *p++ = 0x13000000 | (vtableOffset >> 10); + // jmpl %l0, %lo(privateSnippetExecutor), %g0: + *p++ = 0x81C42000 + | (reinterpret_cast< unsigned int >(privateSnippetExecutor) & 0x3FF); + // or %o1, %lo(vtableOffset), %o1: + *p++ = 0x92126000 | (vtableOffset & 0x3FF); + OSL_ASSERT( + reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block) + 2; + slots[-3].fn = 0; // RTTI + slots[-2].fn = 0; // null + slots[-1].fn = 0; // destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * begin, unsigned char const * end) +{ + bridges::cpp_uno::cc50_solaris_sparc::flushCode(begin, end); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/except.cxx b/bridges/source/cpp_uno/cc50_solaris_sparc/except.cxx new file mode 100644 index 000000000000..84ce64ee1841 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/except.cxx @@ -0,0 +1,451 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <cstddef> +#include <dlfcn.h> +#include <new.h> +#include <typeinfo> +#include <list> +#include <map> +#include <rtl/alloc.h> +#include <osl/diagnose.h> +#include <typelib/typedescription.hxx> +#include <com/sun/star/uno/Any.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "cc50_solaris_sparc.hxx" +#include "flushcode.hxx" +#include <rtl/strbuf.hxx> + +#include "bridges/cpp_uno/shared/arraypointer.hxx" + +#include <hash.cxx> + +// need a += operator for OString and sal_Char +using ::rtl::OUString; +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OUStringToOString; +using ::rtl::OStringToOUString; + +{ + inline OString& operator+=( OString& rString, sal_Char cAdd ) + { + sal_Char add[2]; + add[0] = cAdd; + add[1] = 0; + return rString += add; + } +} + +using namespace std; +using namespace osl; +using namespace com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +static OString toUNOname( const OString & rRTTIname ) +{ + OString aRet; + + const sal_Char* pRTTI = rRTTIname.getStr(); + const sal_Char* pOrg = pRTTI; + const sal_Char* pLast = pRTTI; + + while( 1 ) + { + if( *pRTTI == ':' || ! *pRTTI ) + { + if( aRet.getLength() ) + aRet += "."; + aRet += rRTTIname.copy( pLast - pOrg, pRTTI - pLast ); + while( *pRTTI == ':' ) + pRTTI++; + pLast = pRTTI; + if( ! *pRTTI ) + break; + } + else + pRTTI++; + } + + return aRet; +} +//================================================================================================== +static OString toRTTIname( const OString & rUNOname ) +{ + OStringBuffer aRet( rUNOname.getLength()*2 ); + + sal_Int32 nIndex = 0; + do + { + if( nIndex > 0 ) + aRet.append( "::" ); + aRet.append( rUNOname.getToken( 0, '.', nIndex ) ); + } while( nIndex != -1 ); + + return aRet.makeStringAndClear(); +} +//================================================================================================== + +static OString toRTTImangledname( const OString & rRTTIname ) +{ + if( ! rRTTIname.getLength() ) + return OString(); + + OStringBuffer aRet( rRTTIname.getLength()*2 ); + + aRet.append( "__1n" ); + sal_Int32 nIndex = 0; + do + { + OString aToken( rRTTIname.getToken( 0, ':', nIndex ) ); + int nBytes = aToken.getLength(); + if( nBytes ) + { + if( nBytes > 25 ) + { + aRet.append( (sal_Char)( nBytes/26 + 'a' ) ); + aRet.append( (sal_Char)( nBytes%26 + 'A' ) ); + } + else + aRet.append( (sal_Char)( nBytes + 'A' ) ); + for (sal_Int32 i = 0; i < aToken.getLength(); ++i) { + char c = aToken[i]; + if (c == 'Q') { + aRet.append("QdD"); + } else { + aRet.append(c); + } + } + } + } while( nIndex != -1 ); + + aRet.append( '_' ); + + return aRet.makeStringAndClear(); +} + + +//################################################################################################## +//#### RTTI simulation ############################################################################# +//################################################################################################## + +class RTTIHolder +{ + std::map< OString, void* > aAllRTTI; +public: + ~RTTIHolder(); + + void* getRTTI( const OString& rTypename ); + void* getRTTI_UnoName( const OString& rUnoTypename ) + { return getRTTI( toRTTIname( rUnoTypename ) ); } + + void* insertRTTI( const OString& rTypename ); + void* insertRTTI_UnoName( const OString& rTypename ) + { return insertRTTI( toRTTIname( rTypename ) ); } + void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr ); +}; + +RTTIHolder::~RTTIHolder() +{ + for ( std::map< OString, void* >::const_iterator iPos( aAllRTTI.begin() ); + iPos != aAllRTTI.end(); ++iPos ) + { + delete[] static_cast< char * >(iPos->second); + } +} + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif + +void* RTTIHolder::getRTTI( const OString& rTypename ) +{ + std::map< OString, void* >::iterator element; + + element = aAllRTTI.find( rTypename ); + if( element != aAllRTTI.end() ) + return (*element).second; + + // create rtti structure + element = aAllRTTI.find( rTypename ); + if( element != aAllRTTI.end() ) + return (*element).second; + + return NULL; +} + +void* RTTIHolder::insertRTTI( const OString& rTypename ) +{ + OString aMangledName( toRTTImangledname( rTypename ) ); + NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); + + std::size_t const RTTI_SIZE = 19; // 14??? + void** pRTTI = reinterpret_cast< void ** >( + new char[RTTI_SIZE * sizeof (void *) + strlen(rTypename.getStr()) + 1]); + pRTTI[ 0 ] = reinterpret_cast< void * >(RTTI_SIZE * sizeof (void *)); + pRTTI[ 1 ] = NULL; + pRTTI[ 2 ] = (void*)(7*sizeof(void*)); + pRTTI[ 3 ] = (void*)aHash.getHash()[0]; + pRTTI[ 4 ] = (void*)aHash.getHash()[1]; + pRTTI[ 5 ] = (void*)aHash.getHash()[2]; + pRTTI[ 6 ] = (void*)aHash.getHash()[3]; + pRTTI[ 7 ] = NULL; + pRTTI[ 8 ] = NULL; + + pRTTI[ 9 ] = pRTTI[ 3 ]; + pRTTI[ 10 ] = pRTTI[ 4 ]; + pRTTI[ 11 ] = pRTTI[ 5 ]; + pRTTI[ 12 ] = pRTTI[ 6 ]; + pRTTI[ 13 ] = (void*)0x80000000; + strcpy(reinterpret_cast< char * >(pRTTI + RTTI_SIZE), rTypename.getStr()); + + aAllRTTI[ rTypename ] = (void*)pRTTI; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "generating base RTTI for type %s:\n" + " mangled: %s\n" + " hash: %.8x %.8x %.8x %.8x\n", + rTypename.getStr(), + aMangledName.getStr(), + pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] + ); +#endif + return pRTTI; +} + +//-------------------------------------------------------------------------------------------------- + +void* RTTIHolder::generateRTTI( typelib_CompoundTypeDescription * pCompTypeDescr ) +{ + OString aUNOCompTypeName( OUStringToOString( pCompTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + OString aRTTICompTypeName( toRTTIname( aUNOCompTypeName ) ); + + void* pHaveRTTI = getRTTI( aRTTICompTypeName ); + if( pHaveRTTI ) + return pHaveRTTI; + + if( ! pCompTypeDescr->pBaseTypeDescription ) + // this is a base type + return insertRTTI( aRTTICompTypeName ); + + // get base class RTTI + void* pSuperRTTI = generateRTTI( pCompTypeDescr->pBaseTypeDescription ); + OSL_ENSURE( pSuperRTTI, "could not generate RTTI for supertype !" ); + + // find out the size to allocate for RTTI + void** pInherit = (void**)((sal_uInt32)pSuperRTTI + ((sal_uInt32*)pSuperRTTI)[2] + 8); + int nInherit; + for( nInherit = 1; pInherit[ nInherit*5-1 ] != (void*)0x80000000; nInherit++ ) + ; + + OString aMangledName( toRTTImangledname( aRTTICompTypeName ) ); + NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); + + std::size_t const rttiSize = 14 + nInherit * 5; + void** pRTTI = reinterpret_cast< void ** >( + new char[ + rttiSize * sizeof (void *) + + strlen(aRTTICompTypeName.getStr()) + 1]); + pRTTI[ 0 ] = reinterpret_cast< void * >(rttiSize * sizeof (void *)); + pRTTI[ 1 ] = NULL; + pRTTI[ 2 ] = (void*)(7*sizeof(void*)); + pRTTI[ 3 ] = (void*)aHash.getHash()[0]; + pRTTI[ 4 ] = (void*)aHash.getHash()[1]; + pRTTI[ 5 ] = (void*)aHash.getHash()[2]; + pRTTI[ 6 ] = (void*)aHash.getHash()[3]; + pRTTI[ 7 ] = NULL; + pRTTI[ 8 ] = NULL; + + memcpy( pRTTI+9, pInherit, 4*nInherit*5 ); + pRTTI[ 8 +nInherit*5 ] = NULL; + pRTTI[ 9 +nInherit*5 ] = pRTTI[ 3 ]; + pRTTI[ 10+nInherit*5 ] = pRTTI[ 4 ]; + pRTTI[ 11+nInherit*5 ] = pRTTI[ 5 ]; + pRTTI[ 12+nInherit*5 ] = pRTTI[ 6 ]; + pRTTI[ 13+nInherit*5 ] = (void*)0x80000000; + strcpy( + reinterpret_cast< char * >(pRTTI + rttiSize), + aRTTICompTypeName.getStr()); + + aAllRTTI[ aRTTICompTypeName ] = (void*)pRTTI; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "generating struct RTTI for type %s:\n" + " mangled: %s\n" + " hash: %.8x %.8x %.8X %.8x\n", + aRTTICompTypeName.getStr(), + aMangledName.getStr(), + pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] + ); +#endif + + return pRTTI; +} + +//-------------------------------------------------------------------------------------------------- + +static void deleteException( + void* pExc, unsigned int* thunk, typelib_TypeDescription* pType ) +{ + uno_destructData( + pExc, pType, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + typelib_typedescription_release( pType ); + delete[] thunk; +} + +//__________________________________________________________________________________________________ + +//################################################################################################## +//#### exported #################################################################################### +//################################################################################################## + +void cc50_solaris_sparc_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + bridges::cpp_uno::shared::ArrayPointer< unsigned int > thunkPtr( + new unsigned int[6]); + + typelib_TypeDescription * pTypeDescr = 0; + // will be released by deleteException + typelib_typedescriptionreference_getDescription( &pTypeDescr, pUnoExc->pType ); + + void* pRTTI; + { + static ::osl::Mutex aMutex; + ::osl::Guard< ::osl::Mutex > guard( aMutex ); + + static RTTIHolder * s_pRTTI = 0; + if (! s_pRTTI) + { +#ifdef LEAK_STATIC_DATA + s_pRTTI = new RTTIHolder(); +#else + static RTTIHolder s_aRTTI; + s_pRTTI = &s_aRTTI; +#endif + } + + pRTTI = s_pRTTI->generateRTTI( (typelib_CompoundTypeDescription *)pTypeDescr ); + } + + // a must be + OSL_ENSURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" ); + + void * pCppExc = __Crun::ex_alloc( pTypeDescr->nSize ); + uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + uno_any_destruct( pUnoExc, 0 ); + + unsigned int * thunk = thunkPtr.release(); + // sethi %hi(thunk), %o1: + thunk[0] = 0x13000000 | (reinterpret_cast< unsigned int >(thunk) >> 10); + // or %o1, %lo(thunk), %o1: + thunk[1] = 0x92126000 | (reinterpret_cast< unsigned int >(thunk) & 0x3FF); + // sethi %hi(pTypeDescr), %o2: + thunk[2] = 0x15000000 + | (reinterpret_cast< unsigned int >(pTypeDescr) >> 10); + // sethi %hi(deleteException), %o3 + thunk[3] = 0x17000000 + | (reinterpret_cast< unsigned int >(deleteException) >> 10); + // jmpl %o3, %lo(deleteException), %g0 + thunk[4] = 0x81C2E000 + | (reinterpret_cast< unsigned int >(deleteException) & 0x3FF); + // or %o2, %lo(pTypeDescr), %o2: + thunk[5] = 0x9412A000 + | (reinterpret_cast< unsigned int >(pTypeDescr) & 0x3FF); + bridges::cpp_uno::cc50_solaris_sparc::flushCode(thunk, thunk + 6); + +#pragma disable_warn + void (* f)(void *) = reinterpret_cast< void (*)(void *) >(thunk); +#pragma enable_warn + __Crun::ex_throw(pCppExc, (const __Crun::static_type_info*)pRTTI, f); +} + +void cc50_solaris_sparc_fillUnoException( + void* pCppExc, + const char* pInfo, + uno_Any* pUnoExc, + uno_Mapping * pCpp2Uno ) +{ + OSL_ASSERT( pInfo != 0 ); + OString uno_name( toUNOname( pInfo ) ); + OUString aName( OStringToOUString( + uno_name, RTL_TEXTENCODING_ASCII_US ) ); + typelib_TypeDescription * pExcTypeDescr = 0; + typelib_typedescription_getByName( &pExcTypeDescr, aName.pData ); + + if (pExcTypeDescr == 0) // the thing that should not be + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "exception type not found: ") ) + aName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( + pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( + aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "> c++ exception occurred: %s\n", + ::rtl::OUStringToOString( + pExcTypeDescr->pTypeName, + RTL_TEXTENCODING_ASCII_US ).getStr() ); +#endif + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, pCppExc, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); +} + +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/flushcode.hxx b/bridges/source/cpp_uno/cc50_solaris_sparc/flushcode.hxx new file mode 100644 index 000000000000..5d89d81efed8 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/flushcode.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC50_SOLARIS_SPARC_FLUSHCODE_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC50_SOLARIS_SPARC_FLUSHCODE_HXX + +#include "sal/config.h" + +extern "C" void sync_instruction_memory(caddr_t addr, int len); // from libc + +namespace bridges { namespace cpp_uno { namespace cc50_solaris_sparc { + +/** + * Flush a region of memory into which code has been written dynamically. + */ +inline void flushCode(void const * begin, void const * end) { + sync_instruction_memory( + static_cast< caddr_t >(const_cast< void * >(begin)), + static_cast< char const * >(end) - static_cast< char const * >(begin)); +} + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/hash.cxx b/bridges/source/cpp_uno/cc50_solaris_sparc/hash.cxx new file mode 100644 index 000000000000..29064c19a28f --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/hash.cxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#ifndef TEST +#include <sal/types.h> +#else +typedef unsigned int sal_uInt32; +#endif + +#include <string.h> + +/* + * build a hash for a character buffer using the NIST algorithm + */ + +class NIST_Hash +{ + + // helper functions + sal_uInt32 f1( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return z ^ ( x & ( y ^ z ) ); + } + + sal_uInt32 f2( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return x ^ y ^ z; + } + + sal_uInt32 f3( sal_uInt32 x, sal_uInt32 y, sal_uInt32 z ) + { + return ( x & y ) + ( z & ( x ^ y ) ); + } + + sal_uInt32 rotl( sal_uInt32 nValue, sal_uInt32 nBits ) + { + return ( nValue << nBits ) | ( nValue >> (32-nBits) ); + } + + sal_uInt32 expand_nostore( sal_uInt32 index ) + { + return data[index&15] ^ data[(index-14)&15] ^ data[(index-8)&15] ^ data[(index-3)&15]; + } + + sal_uInt32 expand_store( sal_uInt32 index ) + { + return data[index&15] ^= data[(index-14)&15] ^ data[(index-8)&15] ^ data[(index-3)&15]; + } + + void subRound( sal_uInt32 a, sal_uInt32& b, sal_uInt32 c, sal_uInt32 d, sal_uInt32& e, sal_uInt32 constant, sal_uInt32 datum, sal_uInt32 nFunction ) + { + e += rotl(a,5); + switch( nFunction ) + { + case 1: e += f1( b, c, d );break; + case 2: + case 4: e += f2( b, c, d );break; + case 3: e += f3( b, c, d );break; + } + e += constant + datum; + b = rotl( b, 30 ); + } + + void transform(); + void final(); + + // data members + sal_uInt32 data[16]; + sal_uInt32 hashdata[5]; +public: + NIST_Hash( const char* pString, sal_uInt32 nLen ); + + sal_uInt32 *getHash() { return hashdata; } +}; + +void NIST_Hash::transform() +{ + // constants + const sal_uInt32 K2 = 0x5A827999; + const sal_uInt32 K3 = 0x6ED9EBA1; + const sal_uInt32 K5 = 0x8F1BBCDC; + const sal_uInt32 K10 = 0xCA62C1D6; + + sal_uInt32 a, b, c, d, e; + a = hashdata[0]; + b = hashdata[1]; + c = hashdata[2]; + d = hashdata[3]; + e = hashdata[4]; + + subRound( a, b, c, d, e, K2, data[ 0], 1 ); + subRound( e, a, b, c, d, K2, data[ 1], 1 ); + subRound( d, e, a, b, c, K2, data[ 2], 1 ); + subRound( c, d, e, a, b, K2, data[ 3], 1 ); + subRound( b, c, d, e, a, K2, data[ 4], 1 ); + subRound( a, b, c, d, e, K2, data[ 5], 1 ); + subRound( e, a, b, c, d, K2, data[ 6], 1 ); + subRound( d, e, a, b, c, K2, data[ 7], 1 ); + subRound( c, d, e, a, b, K2, data[ 8], 1 ); + subRound( b, c, d, e, a, K2, data[ 9], 1 ); + subRound( a, b, c, d, e, K2, data[10], 1 ); + subRound( e, a, b, c, d, K2, data[11], 1 ); + subRound( d, e, a, b, c, K2, data[12], 1 ); + subRound( c, d, e, a, b, K2, data[13], 1 ); + subRound( b, c, d, e, a, K2, data[14], 1 ); + subRound( a, b, c, d, e, K2, data[15], 1 ); + subRound( e, a, b, c, d, K2, expand_store( 16 ), 1 ); + subRound( d, e, a, b, c, K2, expand_store( 17 ), 1 ); + subRound( c, d, e, a, b, K2, expand_store( 18 ), 1 ); + subRound( b, c, d, e, a, K2, expand_store( 19 ), 1 ); + + subRound( a, b, c, d, e, K3, expand_store( 20 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 21 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 22 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 23 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 24 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 25 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 26 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 27 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 28 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 29 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 30 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 31 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 32 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 33 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 34 ), 2 ); + subRound( a, b, c, d, e, K3, expand_store( 35 ), 2 ); + subRound( e, a, b, c, d, K3, expand_store( 36 ), 2 ); + subRound( d, e, a, b, c, K3, expand_store( 37 ), 2 ); + subRound( c, d, e, a, b, K3, expand_store( 38 ), 2 ); + subRound( b, c, d, e, a, K3, expand_store( 39 ), 2 ); + + subRound( a, b, c, d, e, K5, expand_store( 40 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 41 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 42 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 43 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 44 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 45 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 46 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 47 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 48 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 49 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 50 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 51 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 52 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 53 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 54 ), 3 ); + subRound( a, b, c, d, e, K5, expand_store( 55 ), 3 ); + subRound( e, a, b, c, d, K5, expand_store( 56 ), 3 ); + subRound( d, e, a, b, c, K5, expand_store( 57 ), 3 ); + subRound( c, d, e, a, b, K5, expand_store( 58 ), 3 ); + subRound( b, c, d, e, a, K5, expand_store( 59 ), 3 ); + + subRound( a, b, c, d, e, K10, expand_store( 60 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 61 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 62 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 63 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 64 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 65 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 66 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 67 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 68 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 69 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 70 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 71 ), 4 ); + subRound( d, e, a, b, c, K10, expand_store( 72 ), 4 ); + subRound( c, d, e, a, b, K10, expand_store( 73 ), 4 ); + subRound( b, c, d, e, a, K10, expand_store( 74 ), 4 ); + subRound( a, b, c, d, e, K10, expand_store( 75 ), 4 ); + subRound( e, a, b, c, d, K10, expand_store( 76 ), 4 ); + subRound( d, e, a, b, c, K10, expand_nostore( 77 ), 4 ); + subRound( c, d, e, a, b, K10, expand_nostore( 78 ), 4 ); + subRound( b, c, d, e, a, K10, expand_nostore( 79 ), 4 ); + + hashdata[0] += a; + hashdata[1] += b; + hashdata[2] += c; + hashdata[3] += d; + hashdata[4] += e; +} + +#define BLOCKSIZE sizeof( data ) + +NIST_Hash::NIST_Hash( const char* pString, sal_uInt32 nLen ) +{ + hashdata[0] = 0x67452301; + hashdata[1] = 0xefcdab89; + hashdata[2] = 0x98badcfe; + hashdata[3] = 0x10325476; + hashdata[4] = 0xc3d2e1f0; + + sal_uInt32 nBytes = nLen; + + while( nLen >= sizeof( data ) ) + { + memcpy( data, pString, sizeof( data ) ); + pString += sizeof( data ); + nLen -= sizeof( data ); + transform(); + } + memcpy( data, pString, nLen ); + ((char*)data)[nLen++] = 0x80; + if( nLen > sizeof( data ) - 8 ) + { + memset( ((char*)data)+nLen, 0, sizeof( data ) - nLen ); + transform(); + memset( data, 0, sizeof( data ) - 8 ); + } + else + memset( ((char*)data)+nLen, 0, sizeof( data ) - 8 - nLen ); + data[14] = 0; + data[15] = nBytes << 3; + transform(); +} + +#ifdef TEST +#include <stdio.h> +int main( int argc, const char** argv ) +{ + const char* pHash = argc < 2 ? argv[0] : argv[1]; + + NIST_Hash aHash( pHash, strlen( pHash ) ); + sal_uInt32* pBits = aHash.getHash(); + + printf( "text : %s\n" + "bits : 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", + pHash, + pBits[0], pBits[1], pBits[2],pBits[3],pBits[4] + ); + return 0; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/makefile.mk b/bridges/source/cpp_uno/cc50_solaris_sparc/makefile.mk new file mode 100644 index 000000000000..74d156abbf75 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=sunpro5_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +# disable check for PIC code as it would complain about +# hand coded assembler +CHECKFORPIC= + +.IF "$(COM)" == "C52" && "$(CPU)"=="S" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/except.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB= i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH= URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +.INCLUDE : target.mk + + +$(SLO)$/%.obj: %.s + CC -KPIC -c -o $(SLO)$/$(@:b).o $< && touch $@ + diff --git a/bridges/source/cpp_uno/cc50_solaris_sparc/uno2cpp.cxx b/bridges/source/cpp_uno/cc50_solaris_sparc/uno2cpp.cxx new file mode 100644 index 000000000000..9d0d139850ec --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/uno2cpp.cxx @@ -0,0 +1,400 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "cc50_solaris_sparc.hxx" + +using namespace com::sun::star::uno; + +using ::rtl::OUString; + +namespace +{ + +extern "C" void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs + ); + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // pCppI is cc50_solaris_sparc this pointer + OSL_ENSURE( pThis, "### no interface given!" ); + + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer( + pCppStack, pParamTypeDescr ); + uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + +// seems that EH registration for callVirtualMethod is not really +// necessary + +// static unsigned long* pFrameInfo = NULL; + +// if( ! pFrameInfo ) +// { +// pFrameInfo = new unsigned long[ 7 ]; +// pFrameInfo[ 0 ] = 0x40000000 | (((unsigned long)__Crun::ex_rethrow_q) >> 2); +// pFrameInfo[ 1 ] = 0x01000000; +// pFrameInfo[ 2 ] = (unsigned long)callVirtualMethodExceptionHandler; +// pFrameInfo[ 3 ] = 0; +// pFrameInfo[ 4 ] = (unsigned long)pFrameInfo - (unsigned long)callVirtualMethodExceptionHandler; +// pFrameInfo[ 5 ] = 0; +// pFrameInfo[ 6 ] = 0; +// _ex_register( pFrameInfo+2, 1 ); +// } + + try + { + int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); + if( nStackLongs & 1 ) + // stack has to be 8 byte aligned + nStackLongs++; + + callVirtualMethod( + pAdjustedThisPtr, + aVtableSlot.index, + pCppReturn, + pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, + nStackLongs + ); + + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( + pCppReturn, pReturnTypeDescr, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + } + } + catch( ... ) + { + void* pExc = __Crun::ex_get(); + const char* pName = __Cimpl::ex_name(); + + // get exception + CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_fillUnoException( + pExc, pName, *ppUnoExc, pThis->getBridge()->getCpp2Uno()); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( + pCppArgs[nIndex], + ppTempParamTypeDescr[nTempIndizes], + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.hxx new file mode 100644 index 000000000000..16f6c1090ff2 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_CALLVIRTUALMETHOD_Hx +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_CALLVIRTUALMETHOD_Hx + +#include "sal/config.h" + +extern "C" void callVirtualMethod( + unsigned long function, long * stack, sal_Int32 excess); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.s b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.s new file mode 100644 index 000000000000..67c5aa39ade5 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.s @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +.global callVirtualMethod +.align 8 +callVirtualMethod: + ! %o0: unsigned long function + ! %o1: unsigned long * stack + ! %o2: sal_Int32 excess + add %o2, 176, %o3 + neg %o3 + save %sp, %o3, %sp + ldx [%i1 + 0 * 8], %o0 + ldx [%i1 + 1 * 8], %o1 + ldx [%i1 + 2 * 8], %o2 + ldx [%i1 + 3 * 8], %o3 + tst %i2 + bz,pt %xcc, 1f + ldx [%i1 + 4 * 8], %o4 + add %i1, 6 * 8, %l0 + add %sp, 2047 + 176, %l1 +0: deccc 8, %i2 + ldx [%l0 + %i2], %l2 + bnz,pt %xcc, 0b + stx %l2, [%l1 + %i2] +1: call %i0 + ldx [%i1 + 5 * 8], %o5 + stx %o0, [%i1 + 0 * 8] + stx %o1, [%i1 + 1 * 8] + stx %o2, [%i1 + 2 * 8] + stx %o3, [%i1 + 3 * 8] + ret + restore +.size callVirtualMethod, . - callVirtualMethod +.type callVirtualMethod, #function diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx new file mode 100644 index 000000000000..c49330b2223f --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx @@ -0,0 +1,614 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" +#include "sal/config.h" + +#include <cstddef> +#include <cstdlib> +#include <cstring> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" +#include "com/sun/star/uno/genfunc.hxx" +#include "osl/diagnose.h" +#include "sal/alloca.h" +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "typelib/typedescription.hxx" +#include "uno/any2.h" +#include "uno/data.h" + +#include "exceptions.hxx" +#include "flushcode.hxx" +#include "fp.hxx" +#include "isdirectreturntype.hxx" +#include "vtableslotcall.hxx" + +namespace { + +namespace css = com::sun::star; + +void loadFpRegsFromStruct(typelib_TypeDescription * type, void * data) { + for (typelib_CompoundTypeDescription * t = + reinterpret_cast< typelib_CompoundTypeDescription * >(type); + t != NULL; t = t->pBaseTypeDescription) + { + for (sal_Int32 i = 0; i < t->nMembers; ++i) { + switch (t->ppTypeRefs[i]->eTypeClass) { + case typelib_TypeClass_FLOAT: + switch (t->pMemberOffsets[i]) { + case 0: + fp_loadf0(reinterpret_cast< float * >(data)); + break; + case 4: + fp_loadf1(reinterpret_cast< float * >(data) + 1); + break; + case 8: + fp_loadf2(reinterpret_cast< float * >(data) + 2); + break; + case 12: + fp_loadf3(reinterpret_cast< float * >(data) + 3); + break; + case 16: + fp_loadf4(reinterpret_cast< float * >(data) + 4); + break; + case 20: + fp_loadf5(reinterpret_cast< float * >(data) + 5); + break; + case 24: + fp_loadf6(reinterpret_cast< float * >(data) + 6); + break; + case 28: + fp_loadf7(reinterpret_cast< float * >(data) + 7); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_DOUBLE: + switch (t->pMemberOffsets[i]) { + case 0: + fp_loadd0(reinterpret_cast< double * >(data)); + break; + case 8: + fp_loadd2(reinterpret_cast< double * >(data) + 1); + break; + case 16: + fp_loadd4(reinterpret_cast< double * >(data) + 2); + break; + case 24: + fp_loadd6(reinterpret_cast< double * >(data) + 3); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); + loadFpRegsFromStruct(td, data); + TYPELIB_DANGER_RELEASE(td); + break; + } + } + } + } +} + +void call( + bridges::cpp_uno::shared::CppInterfaceProxy * proxy, + css::uno::TypeDescription const & description, + bool directReturn, typelib_TypeDescriptionReference * returnType, + sal_Int32 count, typelib_MethodParameter * parameters, + unsigned long * callStack) +{ + typelib_TypeDescription * rtd = NULL; + if (returnType != NULL) { + TYPELIB_DANGER_GET(&rtd, returnType); + } + bool retconv = + rtd != NULL && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); + OSL_ASSERT(!(directReturn && retconv)); + void * retin; + void * retout; + char retbuf[32]; + if (directReturn) { + retin = returnType == NULL ? NULL : retbuf; + } else { + retout = reinterpret_cast< void * >(callStack[0]); + retin = retconv ? alloca(rtd->nSize) : retout; + } + void ** args = static_cast< void ** >(alloca(count * sizeof (void *))); + void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); + typelib_TypeDescription ** argtds = + static_cast< typelib_TypeDescription ** >( + alloca(count * sizeof (typelib_TypeDescription *))); + union fp { float f; double d; }; + fp copies[15]; + sal_Int32 stackPos = directReturn ? 1 : 2; // skip return ptr and this ptr + for (sal_Int32 i = 0; i < count; ++i) { + typelib_TypeDescription * ptd = NULL; + TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); + if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(ptd)) + { + switch (ptd->eTypeClass) { + case typelib_TypeClass_FLOAT: + if (stackPos <= 15) { + switch (stackPos) { + case 1: + fp_storef3(&copies[0].f); + break; + case 2: + fp_storef5(&copies[1].f); + break; + case 3: + fp_storef7(&copies[2].f); + break; + case 4: + fp_storef9(&copies[3].f); + break; + case 5: + fp_storef11(&copies[4].f); + break; + case 6: + fp_storef13(&copies[5].f); + break; + case 7: + fp_storef15(&copies[6].f); + break; + case 8: + fp_storef17(&copies[7].f); + break; + case 9: + fp_storef19(&copies[8].f); + break; + case 10: + fp_storef21(&copies[9].f); + break; + case 11: + fp_storef23(&copies[10].f); + break; + case 12: + fp_storef25(&copies[11].f); + break; + case 13: + fp_storef27(&copies[12].f); + break; + case 14: + fp_storef29(&copies[13].f); + break; + case 15: + fp_storef31(&copies[14].f); + break; + default: + OSL_ASSERT(false); + break; + } + args[i] = &copies[stackPos - 1].f; + } else { + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - sizeof (float)); + } + break; + case typelib_TypeClass_DOUBLE: + if (stackPos <= 15) { + switch (stackPos) { + case 1: + fp_stored2(&copies[0].d); + break; + case 2: + fp_stored4(&copies[1].d); + break; + case 3: + fp_stored6(&copies[2].d); + break; + case 4: + fp_stored8(&copies[3].d); + break; + case 5: + fp_stored10(&copies[4].d); + break; + case 6: + fp_stored12(&copies[5].d); + break; + case 7: + fp_stored14(&copies[6].d); + break; + case 8: + fp_stored16(&copies[7].d); + break; + case 9: + fp_stored18(&copies[8].d); + break; + case 10: + fp_stored20(&copies[9].d); + break; + case 11: + fp_stored22(&copies[10].d); + break; + case 12: + fp_stored24(&copies[11].d); + break; + case 13: + fp_stored26(&copies[12].d); + break; + case 14: + fp_stored28(&copies[13].d); + break; + case 15: + fp_stored30(&copies[14].d); + break; + default: + OSL_ASSERT(false); + break; + } + args[i] = &copies[stackPos - 1].d; + } else { + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - sizeof (double)); + } + break; + default: + OSL_ASSERT(ptd->nSize <= 8); + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - ptd->nSize); + break; + } + argtds[i] = NULL; + TYPELIB_DANGER_RELEASE(ptd); + } else { + cppArgs[i] = reinterpret_cast< void * >(callStack[stackPos]); + if (!parameters[i].bIn) { + args[i] = alloca(ptd->nSize); + argtds[i] = ptd; + } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { + args[i] = alloca(ptd->nSize); + uno_copyAndConvertData( + args[i], reinterpret_cast< void * >(callStack[stackPos]), + ptd, proxy->getBridge()->getCpp2Uno()); + argtds[i] = ptd; + } else { + args[i] = reinterpret_cast< void * >(callStack[stackPos]); + argtds[i] = NULL; + TYPELIB_DANGER_RELEASE(ptd); + } + } + ++stackPos; + } + uno_Any exc; + uno_Any * pexc = &exc; + proxy->getUnoI()->pDispatcher( + proxy->getUnoI(), description.get(), retin, args, &pexc); + if (pexc != NULL) { + for (sal_Int32 i = 0; i < count; ++i) { + if (argtds[i] != NULL) { + if (parameters[i].bIn) { + uno_destructData(args[i], argtds[i], NULL); + } + TYPELIB_DANGER_RELEASE(argtds[i]); + } + } + if (rtd != NULL) { + TYPELIB_DANGER_RELEASE(rtd); + } + bridges::cpp_uno::cc5_solaris_sparc64::raiseException( + &exc, proxy->getBridge()->getUno2Cpp()); + std::abort(); // just in case + } + for (sal_Int32 i = 0; i < count; ++i) { + if (argtds[i] != NULL) { + if (parameters[i].bOut) { + uno_destructData( + cppArgs[i], argtds[i], + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + uno_copyAndConvertData( + cppArgs[i], args[i], argtds[i], + proxy->getBridge()->getUno2Cpp()); + } + uno_destructData(args[i], argtds[i], NULL); + TYPELIB_DANGER_RELEASE(argtds[i]); + } + } + if (directReturn) { + if (rtd != NULL) { + switch (rtd->eTypeClass) { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_BOOLEAN: + callStack[0] = *reinterpret_cast< sal_Bool * >(retbuf); + break; + case typelib_TypeClass_BYTE: + callStack[0] = *reinterpret_cast< sal_Int8 * >(retbuf); + break; + case typelib_TypeClass_SHORT: + callStack[0] = *reinterpret_cast< sal_Int16 * >(retbuf); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + callStack[0] = *reinterpret_cast< sal_uInt16 * >(retbuf); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_ENUM: + callStack[0] = *reinterpret_cast< sal_Int32 * >(retbuf); + break; + case typelib_TypeClass_UNSIGNED_LONG: + callStack[0] = *reinterpret_cast< sal_uInt32 * >(retbuf); + break; + case typelib_TypeClass_HYPER: + callStack[0] = *reinterpret_cast< sal_Int64 * >(retbuf); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + callStack[0] = *reinterpret_cast< sal_uInt64 * >(retbuf); + break; + case typelib_TypeClass_FLOAT: + fp_loadf0(reinterpret_cast< float * >(retbuf)); + break; + case typelib_TypeClass_DOUBLE: + fp_loadd0(reinterpret_cast< double * >(retbuf)); + break; + case typelib_TypeClass_CHAR: + callStack[0] = *reinterpret_cast< sal_Unicode * >(retbuf); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + callStack[0] = reinterpret_cast< unsigned long >( + *reinterpret_cast< void ** >(retbuf)); + break; + case typelib_TypeClass_STRUCT: + loadFpRegsFromStruct(rtd, retbuf); + // fall through + case typelib_TypeClass_ANY: + std::memcpy(callStack, retbuf, rtd->nSize); + break; + default: + OSL_ASSERT(false); + break; + } + } + } else if (retconv) { + uno_copyAndConvertData( + retout, retin, rtd, proxy->getBridge()->getUno2Cpp()); + uno_destructData(retin, rtd, NULL); + } + if (rtd != NULL) { + TYPELIB_DANGER_RELEASE(rtd); + } +} + +extern "C" void vtableCall( + sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * callStack) +{ + bool direct = static_cast< sal_uInt32 >((functionIndex) & 0x80000000) == 0; + functionIndex = static_cast< sal_uInt32 >(functionIndex) & 0x7FFFFFFF; + bridges::cpp_uno::shared::CppInterfaceProxy * proxy + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + reinterpret_cast< char * >(callStack[direct ? 0 : 1]) - + vtableOffset); + typelib_InterfaceTypeDescription * type = proxy->getTypeDescr(); + OSL_ASSERT(functionIndex < type->nMapFunctionIndexToMemberIndex); + sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex]; + css::uno::TypeDescription desc(type->ppAllMembers[pos]); + switch (desc.get()->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) { + // Getter: + call( + proxy, desc, direct, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + desc.get())->pAttributeTypeRef, + 0, NULL, callStack); + } else { + // Setter: + typelib_MethodParameter param = { + NULL, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + desc.get())->pAttributeTypeRef, + true, false }; + call(proxy, desc, true, NULL, 1, ¶m, callStack); + } + break; + case typelib_TypeClass_INTERFACE_METHOD: + switch (functionIndex) { + case 1: + proxy->acquireProxy(); + break; + case 2: + proxy->releaseProxy(); + break; + case 0: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET( + &td, + reinterpret_cast< css::uno::Type * >( + callStack[2])->getTypeLibType()); + if (td != NULL) { + css::uno::XInterface * ifc = NULL; + proxy->getBridge()->getCppEnv()->getRegisteredInterface( + proxy->getBridge()->getCppEnv(), + reinterpret_cast< void ** >(&ifc), + proxy->getOid().pData, + reinterpret_cast< typelib_InterfaceTypeDescription * >( + td)); + if (ifc != NULL) { + uno_any_construct( + reinterpret_cast< uno_Any * >(callStack[0]), &ifc, + td, + reinterpret_cast< uno_AcquireFunc >( + css::uno::cpp_acquire)); + ifc->release(); + TYPELIB_DANGER_RELEASE(td); + break; + } + TYPELIB_DANGER_RELEASE(td); + } + } // fall through + default: + call( + proxy, desc, direct, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->pReturnTypeRef, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->nParams, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->pParams, + callStack); + } + break; + default: + OSL_ASSERT(false); + break; + } +} + +int const codeSnippetSize = 10 * 4; + +unsigned char * generateCodeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool directReturn) +{ + sal_uInt32 index = functionIndex; + if (!directReturn) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + OSL_ASSERT(sizeof (unsigned int) == 4); + // 0*4: save %sp, -176, %sp ! minimal stack frame: + *p++ = 0x9DE3BF50; + // 1*4: rd %pc, %l0: + *p++ = 0xA1414000; + // 2*4: ldx %l0, (8-1)*4, %l0: + *p++ = 0xE05C201C; + // 3*4: sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // 4*4: or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // 5*4: sethi %hi(vtableOffset), %o1: + *p++ = 0x13000000 | (vtableOffset >> 10); + // 6*4: jmpl %l0, %g0, %g0: + *p++ = 0x81C40000; + // 7*4: or %o1, %lo(vtableOffset), %o1: + *p++ = 0x92126000 | (vtableOffset & 0x3FF); + // 8*4: .xword privateSnippetExecutor: + *reinterpret_cast< unsigned long * >(p) = + reinterpret_cast< unsigned long >(vtableSlotCall); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block) + 2; + slots[-3].fn = NULL; // RTTI + slots[-2].fn = NULL; // null + slots[-1].fn = NULL; // destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * begin, unsigned char const * end) +{ + bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin, end); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.cxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.cxx new file mode 100644 index 000000000000..bf6b1512a41d --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.cxx @@ -0,0 +1,462 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" +#include "sal/config.h" + +#include <cstddef> +#include <cstring> +#include <map> +#include <utility> +#include <vector> + +#include "bridges/cpp_uno/shared/arraypointer.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/genfunc.hxx" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "uno/any2.h" +#include "uno/data.h" +#include "uno/mapping.h" + +#include "exceptions.hxx" +#include "flushcode.hxx" + +namespace { + +namespace css = com::sun::star; + +typedef void (* Function)(void *); + +Function toFunction(void * pointer) { +#pragma disable_warn + return reinterpret_cast< Function >(pointer); +#pragma enable_warn +} + +bool toUnoName(char const * rttiName, rtl::OUString * unoName) { + rtl::OStringBuffer buf; + for (;;) { + char const * p = std::strchr(rttiName, ':'); + if (p == NULL) { + buf.append(rttiName); + break; + } + if (p - rttiName > SAL_MAX_INT32) { + return false; + } + buf.append(rttiName, sal::static_int_cast< sal_Int32 >(p - rttiName)); + buf.append("."); + while (*p == ':') { + ++p; + } + rttiName = p; + } + *unoName = rtl::OStringToOUString( + buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + //TODO: check conversion failure + return true; +} + +class NistHash { +public: + NistHash(rtl::OString const & text); + + sal_uInt32 hashdata[5]; + +private: + static sal_uInt32 f1(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) + { return z ^ (x & (y ^ z)); } + + static sal_uInt32 f2(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) + { return x ^ y ^ z; } + + static sal_uInt32 f3(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) + { return (x & y) + (z & (x ^ y)); } + + static sal_uInt32 rotl(sal_uInt32 value, sal_uInt32 bits) + { return (value << bits) | (value >> (32 - bits)); } + + sal_uInt32 expand_nostore(sal_uInt32 index) { + return data[index & 15] ^ data[(index - 14) & 15] ^ + data[(index - 8) & 15] ^ data[(index - 3) & 15]; + } + + sal_uInt32 expand_store(sal_uInt32 index) { + return data[index & 15] ^= data[(index - 14) & 15] ^ + data[(index - 8) & 15] ^ data[(index - 3) & 15]; + } + + void subRound( + sal_uInt32 a, sal_uInt32 & b, sal_uInt32 c, sal_uInt32 d, + sal_uInt32 & e, sal_uInt32 constant, sal_uInt32 datum, + sal_uInt32 function) + { + e += rotl(a, 5); + switch (function) { + case 1: + e += f1(b, c, d); + break; + case 2: + case 4: + e += f2(b, c, d); + break; + case 3: + e += f3(b, c, d); + break; + } + e += constant + datum; + b = rotl(b, 30); + } + + void transform(); + + sal_uInt32 data[16]; +}; + +NistHash::NistHash(rtl::OString const & text) { + hashdata[0] = 0x67452301; + hashdata[1] = 0xefcdab89; + hashdata[2] = 0x98badcfe; + hashdata[3] = 0x10325476; + hashdata[4] = 0xc3d2e1f0; + char const * p = text.getStr(); + sal_Int32 n = text.getLength(); + while (n >= sizeof data) { + std::memcpy(data, p, sizeof data); + p += sizeof data; + n -= sizeof data; + transform(); + } + std::memcpy(data, p, n); + reinterpret_cast< unsigned char *>(data)[n++] = 0x80; + if (n > sizeof data - 8) { + std::memset(reinterpret_cast< char * >(data) + n, 0, sizeof data - n); + transform(); + std::memset(data, 0, sizeof data - 8); + } else { + std::memset( + reinterpret_cast< char * >(data) + n, 0, sizeof data - 8 - n); + } + data[14] = 0; + data[15] = text.getLength() << 3; + transform(); +} + +void NistHash::transform() { + sal_uInt32 const K2 = 0x5A827999; + sal_uInt32 const K3 = 0x6ED9EBA1; + sal_uInt32 const K5 = 0x8F1BBCDC; + sal_uInt32 const K10 = 0xCA62C1D6; + sal_uInt32 a = hashdata[0]; + sal_uInt32 b = hashdata[1]; + sal_uInt32 c = hashdata[2]; + sal_uInt32 d = hashdata[3]; + sal_uInt32 e = hashdata[4]; + subRound(a, b, c, d, e, K2, data[ 0], 1); + subRound(e, a, b, c, d, K2, data[ 1], 1); + subRound(d, e, a, b, c, K2, data[ 2], 1); + subRound(c, d, e, a, b, K2, data[ 3], 1); + subRound(b, c, d, e, a, K2, data[ 4], 1); + subRound(a, b, c, d, e, K2, data[ 5], 1); + subRound(e, a, b, c, d, K2, data[ 6], 1); + subRound(d, e, a, b, c, K2, data[ 7], 1); + subRound(c, d, e, a, b, K2, data[ 8], 1); + subRound(b, c, d, e, a, K2, data[ 9], 1); + subRound(a, b, c, d, e, K2, data[10], 1); + subRound(e, a, b, c, d, K2, data[11], 1); + subRound(d, e, a, b, c, K2, data[12], 1); + subRound(c, d, e, a, b, K2, data[13], 1); + subRound(b, c, d, e, a, K2, data[14], 1); + subRound(a, b, c, d, e, K2, data[15], 1); + subRound(e, a, b, c, d, K2, expand_store(16), 1); + subRound(d, e, a, b, c, K2, expand_store(17), 1); + subRound(c, d, e, a, b, K2, expand_store(18), 1); + subRound(b, c, d, e, a, K2, expand_store(19), 1); + subRound(a, b, c, d, e, K3, expand_store(20), 2); + subRound(e, a, b, c, d, K3, expand_store(21), 2); + subRound(d, e, a, b, c, K3, expand_store(22), 2); + subRound(c, d, e, a, b, K3, expand_store(23), 2); + subRound(b, c, d, e, a, K3, expand_store(24), 2); + subRound(a, b, c, d, e, K3, expand_store(25), 2); + subRound(e, a, b, c, d, K3, expand_store(26), 2); + subRound(d, e, a, b, c, K3, expand_store(27), 2); + subRound(c, d, e, a, b, K3, expand_store(28), 2); + subRound(b, c, d, e, a, K3, expand_store(29), 2); + subRound(a, b, c, d, e, K3, expand_store(30), 2); + subRound(e, a, b, c, d, K3, expand_store(31), 2); + subRound(d, e, a, b, c, K3, expand_store(32), 2); + subRound(c, d, e, a, b, K3, expand_store(33), 2); + subRound(b, c, d, e, a, K3, expand_store(34), 2); + subRound(a, b, c, d, e, K3, expand_store(35), 2); + subRound(e, a, b, c, d, K3, expand_store(36), 2); + subRound(d, e, a, b, c, K3, expand_store(37), 2); + subRound(c, d, e, a, b, K3, expand_store(38), 2); + subRound(b, c, d, e, a, K3, expand_store(39), 2); + subRound(a, b, c, d, e, K5, expand_store(40), 3); + subRound(e, a, b, c, d, K5, expand_store(41), 3); + subRound(d, e, a, b, c, K5, expand_store(42), 3); + subRound(c, d, e, a, b, K5, expand_store(43), 3); + subRound(b, c, d, e, a, K5, expand_store(44), 3); + subRound(a, b, c, d, e, K5, expand_store(45), 3); + subRound(e, a, b, c, d, K5, expand_store(46), 3); + subRound(d, e, a, b, c, K5, expand_store(47), 3); + subRound(c, d, e, a, b, K5, expand_store(48), 3); + subRound(b, c, d, e, a, K5, expand_store(49), 3); + subRound(a, b, c, d, e, K5, expand_store(50), 3); + subRound(e, a, b, c, d, K5, expand_store(51), 3); + subRound(d, e, a, b, c, K5, expand_store(52), 3); + subRound(c, d, e, a, b, K5, expand_store(53), 3); + subRound(b, c, d, e, a, K5, expand_store(54), 3); + subRound(a, b, c, d, e, K5, expand_store(55), 3); + subRound(e, a, b, c, d, K5, expand_store(56), 3); + subRound(d, e, a, b, c, K5, expand_store(57), 3); + subRound(c, d, e, a, b, K5, expand_store(58), 3); + subRound(b, c, d, e, a, K5, expand_store(59), 3); + subRound(a, b, c, d, e, K10, expand_store(60), 4); + subRound(e, a, b, c, d, K10, expand_store(61), 4); + subRound(d, e, a, b, c, K10, expand_store(62), 4); + subRound(c, d, e, a, b, K10, expand_store(63), 4); + subRound(b, c, d, e, a, K10, expand_store(64), 4); + subRound(a, b, c, d, e, K10, expand_store(65), 4); + subRound(e, a, b, c, d, K10, expand_store(66), 4); + subRound(d, e, a, b, c, K10, expand_store(67), 4); + subRound(c, d, e, a, b, K10, expand_store(68), 4); + subRound(b, c, d, e, a, K10, expand_store(69), 4); + subRound(a, b, c, d, e, K10, expand_store(70), 4); + subRound(e, a, b, c, d, K10, expand_store(71), 4); + subRound(d, e, a, b, c, K10, expand_store(72), 4); + subRound(c, d, e, a, b, K10, expand_store(73), 4); + subRound(b, c, d, e, a, K10, expand_store(74), 4); + subRound(a, b, c, d, e, K10, expand_store(75), 4); + subRound(e, a, b, c, d, K10, expand_store(76), 4); + subRound(d, e, a, b, c, K10, expand_nostore(77), 4); + subRound(c, d, e, a, b, K10, expand_nostore(78), 4); + subRound(b, c, d, e, a, K10, expand_nostore(79), 4); + hashdata[0] += a; + hashdata[1] += b; + hashdata[2] += c; + hashdata[3] += d; + hashdata[4] += e; +} + +class RttiMap { +public: + static __Crun::static_type_info const * get( + typelib_CompoundTypeDescription const * type); + +private: + RttiMap(); // not defined + RttiMap(RttiMap &); // not defined + ~RttiMap(); // not defined + void operator =(RttiMap &); // not defined + + struct Data { + __Crun::static_type_info * info; + rtl::OString cppName; + std::vector< __Crun::class_base_descr > bases; + }; + typedef std::map< rtl::OUString, Data > Map; + + static void toCppNames( + rtl::OUString const & unoName, rtl::OString * cppName, + rtl::OString * rttiName); + + static Data const & get_(typelib_CompoundTypeDescription const * type); + + static osl::Mutex m_mutex; + static Map * m_map; +}; + +osl::Mutex RttiMap::m_mutex; +RttiMap::Map * RttiMap::m_map; + +__Crun::static_type_info const * RttiMap::get( + typelib_CompoundTypeDescription const * type) +{ + osl::MutexGuard g(m_mutex); + if (m_map == NULL) { + m_map = new Map; // leaked + } + return get_(type).info; +} + +void RttiMap::toCppNames( + rtl::OUString const & unoName, rtl::OString * cppName, + rtl::OString * rttiName) +{ + OSL_ASSERT(cppName != NULL && rttiName != NULL); + rtl::OStringBuffer bc; + rtl::OStringBuffer br; + br.append("__1n"); + for (sal_Int32 i = 0; i != -1;) { + rtl::OUString tok(unoName.getToken(0, '.', i)); + bc.append(rtl::OUStringToOString(tok, RTL_TEXTENCODING_UTF8)); + // conversion should never fail, as tok should be well-formed ASCII + if (i != -1) { + bc.append("::"); + } + sal_Int32 len = tok.getLength(); + sal_Int32 pos = br.getLength(); + for (sal_Int32 n = len / 26; n > 0; n /= 26) { + br.insert(pos, static_cast< char >('a' + (n % 26))); + } + br.append(static_cast< char >('A' + (len % 26))); + for (sal_Int32 j = 0; j < len; ++j) { + sal_Unicode c = tok[j]; + OSL_ASSERT( + c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || + c >= 'a' && c <= 'z'); + if (c == 'Q') { + br.append("QdD"); + } else { + br.append(static_cast< char >(c)); + } + } + } + br.append('_'); + *cppName = bc.makeStringAndClear(); + *rttiName = br.makeStringAndClear(); +} + +RttiMap::Data const & RttiMap::get_( + typelib_CompoundTypeDescription const * type) +{ + rtl::OUString name(type->aBase.pTypeName); + Map::iterator it(m_map->find(name)); + if (it == m_map->end()) { + it = m_map->insert(std::make_pair(name, Data())).first; + Data & data = it->second; + rtl::OString rttiName; + toCppNames(name, &data.cppName, &rttiName); + data.info = new __Crun::static_type_info; + data.info->ty_name = data.cppName.getStr() - + reinterpret_cast< char * >(&data.info->ty_name); + data.info->reserved = 0; + NistHash hash(rttiName); + data.info->type_hash[0] = hash.hashdata[0]; + data.info->type_hash[1] = hash.hashdata[1]; + data.info->type_hash[2] = hash.hashdata[2]; + data.info->type_hash[3] = hash.hashdata[3]; + data.info->flags = 0; + data.info->cv_qualifiers = 0; + if (type->pBaseTypeDescription != NULL) { + data.bases = get_(type->pBaseTypeDescription).bases; + OSL_ASSERT(!data.bases.empty()); + data.bases.back().offset = 0; + } + __Crun::class_base_descr last; + last.type_hash[0] = data.info->type_hash[0]; + last.type_hash[1] = data.info->type_hash[1]; + last.type_hash[2] = data.info->type_hash[2]; + last.type_hash[3] = data.info->type_hash[3]; + last.offset = 0x8000000000000000; + data.bases.push_back(last); + data.info->base_table = reinterpret_cast< char * >(&data.bases[0]) - + reinterpret_cast< char * >(&data.info->base_table); + } + return it->second; +} + +void deleteException( + void * exception, unsigned int * thunk, typelib_TypeDescription * type) +{ + uno_destructData( + exception, type, + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + typelib_typedescription_release(type); + delete[] thunk; +} + +} + +namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { + +void raiseException(uno_Any * exception, uno_Mapping * unoToCpp) { + bridges::cpp_uno::shared::ArrayPointer< unsigned long > thunkPtr( + new unsigned long[4]); + typelib_TypeDescription * type = NULL; + typelib_typedescriptionreference_getDescription(&type, exception->pType); + __Crun::static_type_info const * rtti = RttiMap::get( + reinterpret_cast< typelib_CompoundTypeDescription * >(type)); + void * exc = __Crun::ex_alloc(type->nSize); + uno_copyAndConvertData(exc, exception->pData, type, unoToCpp); + uno_any_destruct(exception, NULL); + unsigned long * thunk = thunkPtr.release(); + // 0*4: rd %pc, %o1: + // 1*4: ldx %o1, (6-0)*4, %o3: + thunk[0] = 0x93414000D65A6018; + // 2*4: jmpl %o3, %g0, %g0: + // 3*4: ldx %o1, (4-0)*4, %o2: + thunk[1] = 0x81C2C000D45A6010; + // 4*4: .xword type: + thunk[2] = reinterpret_cast< unsigned long >(type); + // 6*4: .xword deleteException: + thunk[3] = reinterpret_cast< unsigned long >(deleteException); + flushCode(thunk, thunk + 4); + __Crun::ex_throw(exc, rtti, toFunction(thunk)); +} + +void fillUnoException( + void * cppException, char const * cppName, uno_Any * unoException, + uno_Mapping * cppToUno) +{ + rtl::OUString name; + typelib_TypeDescription * type = NULL; + if (toUnoName(cppName, &name)) { + typelib_typedescription_getByName(&type, name.pData); + } + if (type == NULL || type->eTypeClass != typelib_TypeClass_EXCEPTION) { + css::uno::RuntimeException exc( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Not a UNO exception type: ")) + + name), + css::uno::Reference< css::uno::XInterface >()); + uno_type_any_constructAndConvert( + unoException, &exc, getCppuType(&exc).getTypeLibType(), cppToUno); + } else { + uno_any_constructAndConvert(unoException, cppException, type, cppToUno); + } + if (type != NULL) { + typelib_typedescription_release(type); + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.hxx new file mode 100644 index 000000000000..8ba17dad842f --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_EXCEPTIONS_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_EXCEPTIONS_HXX + +#include "sal/config.h" + +#include <cstddef> + +#include "typelib/typedescription.h" +#include "uno/any2.h" +#include "uno/mapping.h" + +// Private CC5 structures and functions: +namespace __Crun { + struct class_base_descr { + int type_hash[4]; + std::size_t offset; + }; + struct static_type_info { + std::ptrdiff_t ty_name; + std::ptrdiff_t reserved; + std::ptrdiff_t base_table; + int type_hash[4]; + unsigned int flags; + unsigned int cv_qualifiers; + }; + void * ex_alloc(unsigned long); + void ex_throw(void *, static_type_info const *, void (*)(void *)); + void * ex_get(); + void ex_rethrow_q() throw (); +} +namespace __Cimpl { + char const * ex_name(); +} + +namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { + +void raiseException(uno_Any * exception, uno_Mapping * unoToCpp); + +void fillUnoException( + void * cppException, char const * cppName, uno_Any * unoException, + uno_Mapping * cppToUno); + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/flushcode.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/flushcode.hxx new file mode 100644 index 000000000000..de7028d3faa2 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/flushcode.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_FLUSHCODE_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_FLUSHCODE_HXX + +#include "sal/config.h" + +extern "C" void sync_instruction_memory(caddr_t addr, int len); // from libc + +namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { + +/** + * Flush a region of memory into which code has been written dynamically. + */ +inline void flushCode(void const * begin, void const * end) { + sync_instruction_memory( + static_cast< caddr_t >(const_cast< void * >(begin)), + static_cast< char const * >(end) - static_cast< char const * >(begin)); +} + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.hxx new file mode 100644 index 000000000000..ba32b141d338 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.hxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_FP_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_FP_HXX + +#include "sal/config.h" + +extern "C" { + +void fp_loadf0(float *); +void fp_loadf1(float *); +void fp_loadf2(float *); +void fp_loadf3(float *); +void fp_loadf4(float *); +void fp_loadf5(float *); +void fp_loadf6(float *); +void fp_loadf7(float *); +void fp_loadf9(float *); +void fp_loadf11(float *); +void fp_loadf13(float *); +void fp_loadf15(float *); +void fp_loadf17(float *); +void fp_loadf19(float *); +void fp_loadf21(float *); +void fp_loadf23(float *); +void fp_loadf25(float *); +void fp_loadf27(float *); +void fp_loadf29(float *); +void fp_loadf31(float *); + +void fp_storef0(float *); +void fp_storef1(float *); +void fp_storef2(float *); +void fp_storef3(float *); +void fp_storef4(float *); +void fp_storef5(float *); +void fp_storef6(float *); +void fp_storef7(float *); +void fp_storef9(float *); +void fp_storef11(float *); +void fp_storef13(float *); +void fp_storef15(float *); +void fp_storef17(float *); +void fp_storef19(float *); +void fp_storef21(float *); +void fp_storef23(float *); +void fp_storef25(float *); +void fp_storef27(float *); +void fp_storef29(float *); +void fp_storef31(float *); + +void fp_loadd0(double *); +void fp_loadd2(double *); +void fp_loadd4(double *); +void fp_loadd6(double *); +void fp_loadd8(double *); +void fp_loadd10(double *); +void fp_loadd12(double *); +void fp_loadd14(double *); +void fp_loadd16(double *); +void fp_loadd18(double *); +void fp_loadd20(double *); +void fp_loadd22(double *); +void fp_loadd24(double *); +void fp_loadd26(double *); +void fp_loadd28(double *); +void fp_loadd30(double *); + +void fp_stored0(double *); +void fp_stored2(double *); +void fp_stored4(double *); +void fp_stored6(double *); +void fp_stored8(double *); +void fp_stored10(double *); +void fp_stored12(double *); +void fp_stored14(double *); +void fp_stored16(double *); +void fp_stored18(double *); +void fp_stored20(double *); +void fp_stored22(double *); +void fp_stored24(double *); +void fp_stored26(double *); +void fp_stored28(double *); +void fp_stored30(double *); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.s b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.s new file mode 100644 index 000000000000..92216d4e08dd --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.s @@ -0,0 +1,602 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +.global fp_loadf0 +.align 8 +fp_loadf0: + retl + ld [%o0], %f0 +.size fp_loadf0, . - fp_loadf0 +.type fp_loadf0, #function + +.global fp_loadf1 +.align 8 +fp_loadf1: + retl + ld [%o0], %f1 +.size fp_loadf1, . - fp_loadf1 +.type fp_loadf1, #function + +.global fp_loadf2 +.align 8 +fp_loadf2: + retl + ld [%o0], %f2 +.size fp_loadf2, . - fp_loadf2 +.type fp_loadf2, #function + +.global fp_loadf3 +.align 8 +fp_loadf3: + retl + ld [%o0], %f3 +.size fp_loadf3, . - fp_loadf3 +.type fp_loadf3, #function + +.global fp_loadf4 +.align 8 +fp_loadf4: + retl + ld [%o0], %f4 +.size fp_loadf4, . - fp_loadf4 +.type fp_loadf4, #function + +.global fp_loadf5 +.align 8 +fp_loadf5: + retl + ld [%o0], %f5 +.size fp_loadf5, . - fp_loadf5 +.type fp_loadf5, #function + +.global fp_loadf6 +.align 8 +fp_loadf6: + retl + ld [%o0], %f6 +.size fp_loadf6, . - fp_loadf6 +.type fp_loadf6, #function + +.global fp_loadf7 +.align 8 +fp_loadf7: + retl + ld [%o0], %f7 +.size fp_loadf7, . - fp_loadf7 +.type fp_loadf7, #function + +.global fp_loadf9 +.align 8 +fp_loadf9: + retl + ld [%o0], %f9 +.size fp_loadf9, . - fp_loadf9 +.type fp_loadf9, #function + +.global fp_loadf11 +.align 8 +fp_loadf11: + retl + ld [%o0], %f11 +.size fp_loadf11, . - fp_loadf11 +.type fp_loadf11, #function + +.global fp_loadf13 +.align 8 +fp_loadf13: + retl + ld [%o0], %f13 +.size fp_loadf13, . - fp_loadf13 +.type fp_loadf13, #function + +.global fp_loadf15 +.align 8 +fp_loadf15: + retl + ld [%o0], %f15 +.size fp_loadf15, . - fp_loadf15 +.type fp_loadf15, #function + +.global fp_loadf17 +.align 8 +fp_loadf17: + retl + ld [%o0], %f17 +.size fp_loadf17, . - fp_loadf17 +.type fp_loadf17, #function + +.global fp_loadf19 +.align 8 +fp_loadf19: + retl + ld [%o0], %f19 +.size fp_loadf19, . - fp_loadf19 +.type fp_loadf19, #function + +.global fp_loadf21 +.align 8 +fp_loadf21: + retl + ld [%o0], %f21 +.size fp_loadf21, . - fp_loadf21 +.type fp_loadf21, #function + +.global fp_loadf23 +.align 8 +fp_loadf23: + retl + ld [%o0], %f23 +.size fp_loadf23, . - fp_loadf23 +.type fp_loadf23, #function + +.global fp_loadf25 +.align 8 +fp_loadf25: + retl + ld [%o0], %f25 +.size fp_loadf25, . - fp_loadf25 +.type fp_loadf25, #function + +.global fp_loadf27 +.align 8 +fp_loadf27: + retl + ld [%o0], %f27 +.size fp_loadf27, . - fp_loadf27 +.type fp_loadf27, #function + +.global fp_loadf29 +.align 8 +fp_loadf29: + retl + ld [%o0], %f29 +.size fp_loadf29, . - fp_loadf29 +.type fp_loadf29, #function + +.global fp_loadf31 +.align 8 +fp_loadf31: + retl + ld [%o0], %f31 +.size fp_loadf31, . - fp_loadf31 +.type fp_loadf31, #function + +.global fp_storef0 +.align 8 +fp_storef0: + retl + st %f0, [%o0] +.size fp_storef0, . - fp_storef0 +.type fp_storef0, #function + +.global fp_storef1 +.align 8 +fp_storef1: + retl + st %f1, [%o0] +.size fp_storef1, . - fp_storef1 +.type fp_storef1, #function + +.global fp_storef2 +.align 8 +fp_storef2: + retl + st %f2, [%o0] +.size fp_storef2, . - fp_storef2 +.type fp_storef2, #function + +.global fp_storef3 +.align 8 +fp_storef3: + retl + st %f3, [%o0] +.size fp_storef3, . - fp_storef3 +.type fp_storef3, #function + +.global fp_storef4 +.align 8 +fp_storef4: + retl + st %f4, [%o0] +.size fp_storef4, . - fp_storef4 +.type fp_storef4, #function + +.global fp_storef5 +.align 8 +fp_storef5: + retl + st %f5, [%o0] +.size fp_storef5, . - fp_storef5 +.type fp_storef5, #function + +.global fp_storef6 +.align 8 +fp_storef6: + retl + st %f6, [%o0] +.size fp_storef6, . - fp_storef6 +.type fp_storef6, #function + +.global fp_storef7 +.align 8 +fp_storef7: + retl + st %f7, [%o0] +.size fp_storef7, . - fp_storef7 +.type fp_storef7, #function + +.global fp_storef9 +.align 8 +fp_storef9: + retl + st %f9, [%o0] +.size fp_storef9, . - fp_storef9 +.type fp_storef9, #function + +.global fp_storef11 +.align 8 +fp_storef11: + retl + st %f11, [%o0] +.size fp_storef11, . - fp_storef11 +.type fp_storef11, #function + +.global fp_storef13 +.align 8 +fp_storef13: + retl + st %f13, [%o0] +.size fp_storef13, . - fp_storef13 +.type fp_storef13, #function + +.global fp_storef15 +.align 8 +fp_storef15: + retl + st %f15, [%o0] +.size fp_storef15, . - fp_storef15 +.type fp_storef15, #function + +.global fp_storef17 +.align 8 +fp_storef17: + retl + st %f17, [%o0] +.size fp_storef17, . - fp_storef17 +.type fp_storef17, #function + +.global fp_storef19 +.align 8 +fp_storef19: + retl + st %f19, [%o0] +.size fp_storef19, . - fp_storef19 +.type fp_storef19, #function + +.global fp_storef21 +.align 8 +fp_storef21: + retl + st %f21, [%o0] +.size fp_storef21, . - fp_storef21 +.type fp_storef21, #function + +.global fp_storef23 +.align 8 +fp_storef23: + retl + st %f23, [%o0] +.size fp_storef23, . - fp_storef23 +.type fp_storef23, #function + +.global fp_storef25 +.align 8 +fp_storef25: + retl + st %f25, [%o0] +.size fp_storef25, . - fp_storef25 +.type fp_storef25, #function + +.global fp_storef27 +.align 8 +fp_storef27: + retl + st %f27, [%o0] +.size fp_storef27, . - fp_storef27 +.type fp_storef27, #function + +.global fp_storef29 +.align 8 +fp_storef29: + retl + st %f29, [%o0] +.size fp_storef29, . - fp_storef29 +.type fp_storef29, #function + +.global fp_storef31 +.align 8 +fp_storef31: + retl + st %f31, [%o0] +.size fp_storef31, . - fp_storef31 +.type fp_storef31, #function + +.global fp_loadd0 +.align 8 +fp_loadd0: + retl + ldd [%o0], %f0 +.size fp_loadd0, . - fp_loadd0 +.type fp_loadd0, #function + +.global fp_loadd2 +.align 8 +fp_loadd2: + retl + ldd [%o0], %f2 +.size fp_loadd2, . - fp_loadd2 +.type fp_loadd2, #function + +.global fp_loadd4 +.align 8 +fp_loadd4: + retl + ldd [%o0], %f4 +.size fp_loadd4, . - fp_loadd4 +.type fp_loadd4, #function + +.global fp_loadd6 +.align 8 +fp_loadd6: + retl + ldd [%o0], %f6 +.size fp_loadd6, . - fp_loadd6 +.type fp_loadd6, #function + +.global fp_loadd8 +.align 8 +fp_loadd8: + retl + ldd [%o0], %f8 +.size fp_loadd8, . - fp_loadd8 +.type fp_loadd8, #function + +.global fp_loadd10 +.align 8 +fp_loadd10: + retl + ldd [%o0], %f10 +.size fp_loadd10, . - fp_loadd10 +.type fp_loadd10, #function + +.global fp_loadd12 +.align 8 +fp_loadd12: + retl + ldd [%o0], %f12 +.size fp_loadd12, . - fp_loadd12 +.type fp_loadd12, #function + +.global fp_loadd14 +.align 8 +fp_loadd14: + retl + ldd [%o0], %f14 +.size fp_loadd14, . - fp_loadd14 +.type fp_loadd14, #function + +.global fp_loadd16 +.align 8 +fp_loadd16: + retl + ldd [%o0], %f16 +.size fp_loadd16, . - fp_loadd16 +.type fp_loadd16, #function + +.global fp_loadd18 +.align 8 +fp_loadd18: + retl + ldd [%o0], %f18 +.size fp_loadd18, . - fp_loadd18 +.type fp_loadd18, #function + +.global fp_loadd20 +.align 8 +fp_loadd20: + retl + ldd [%o0], %f20 +.size fp_loadd20, . - fp_loadd20 +.type fp_loadd20, #function + +.global fp_loadd22 +.align 8 +fp_loadd22: + retl + ldd [%o0], %f22 +.size fp_loadd22, . - fp_loadd22 +.type fp_loadd22, #function + +.global fp_loadd24 +.align 8 +fp_loadd24: + retl + ldd [%o0], %f24 +.size fp_loadd24, . - fp_loadd24 +.type fp_loadd24, #function + +.global fp_loadd26 +.align 8 +fp_loadd26: + retl + ldd [%o0], %f26 +.size fp_loadd26, . - fp_loadd26 +.type fp_loadd26, #function + +.global fp_loadd28 +.align 8 +fp_loadd28: + retl + ldd [%o0], %f28 +.size fp_loadd28, . - fp_loadd28 +.type fp_loadd28, #function + +.global fp_loadd30 +.align 8 +fp_loadd30: + retl + ldd [%o0], %f30 +.size fp_loadd30, . - fp_loadd30 +.type fp_loadd30, #function + +.global fp_stored0 +.align 8 +fp_stored0: + retl + std %f0, [%o0] +.size fp_stored0, . - fp_stored0 +.type fp_stored0, #function + +.global fp_stored2 +.align 8 +fp_stored2: + retl + std %f2, [%o0] +.size fp_stored2, . - fp_stored2 +.type fp_stored2, #function + +.global fp_stored4 +.align 8 +fp_stored4: + retl + std %f4, [%o0] +.size fp_stored4, . - fp_stored4 +.type fp_stored4, #function + +.global fp_stored6 +.align 8 +fp_stored6: + retl + std %f6, [%o0] +.size fp_stored6, . - fp_stored6 +.type fp_stored6, #function + +.global fp_stored8 +.align 8 +fp_stored8: + retl + std %f8, [%o0] +.size fp_stored8, . - fp_stored8 +.type fp_stored8, #function + +.global fp_stored10 +.align 8 +fp_stored10: + retl + std %f10, [%o0] +.size fp_stored10, . - fp_stored10 +.type fp_stored10, #function + +.global fp_stored12 +.align 8 +fp_stored12: + retl + std %f12, [%o0] +.size fp_stored12, . - fp_stored12 +.type fp_stored12, #function + +.global fp_stored14 +.align 8 +fp_stored14: + retl + std %f14, [%o0] +.size fp_stored14, . - fp_stored14 +.type fp_stored14, #function + +.global fp_stored16 +.align 8 +fp_stored16: + retl + std %f16, [%o0] +.size fp_stored16, . - fp_stored16 +.type fp_stored16, #function + +.global fp_stored18 +.align 8 +fp_stored18: + retl + std %f18, [%o0] +.size fp_stored18, . - fp_stored18 +.type fp_stored18, #function + +.global fp_stored20 +.align 8 +fp_stored20: + retl + std %f20, [%o0] +.size fp_stored20, . - fp_stored20 +.type fp_stored20, #function + +.global fp_stored22 +.align 8 +fp_stored22: + retl + std %f22, [%o0] +.size fp_stored22, . - fp_stored22 +.type fp_stored22, #function + +.global fp_stored24 +.align 8 +fp_stored24: + retl + std %f24, [%o0] +.size fp_stored24, . - fp_stored24 +.type fp_stored24, #function + +.global fp_stored26 +.align 8 +fp_stored26: + retl + std %f26, [%o0] +.size fp_stored26, . - fp_stored26 +.type fp_stored26, #function + +.global fp_stored28 +.align 8 +fp_stored28: + retl + std %f28, [%o0] +.size fp_stored28, . - fp_stored28 +.type fp_stored28, #function + +.global fp_stored30 +.align 8 +fp_stored30: + retl + std %f30, [%o0] +.size fp_stored30, . - fp_stored30 +.type fp_stored30, #function diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.cxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.cxx new file mode 100644 index 000000000000..9b004078c35f --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" +#include "sal/config.h" + +#include <cstddef> + +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +#include "isdirectreturntype.hxx" + +namespace { + +bool isPodStruct(typelib_CompoundTypeDescription * type) { + for (; type != NULL; type = type->pBaseTypeDescription) { + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + if (!bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + type->ppTypeRefs[i])) + { + return false; + } + } + } + return true; +} + +} + +namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { + +bool isDirectReturnType(typelib_TypeDescriptionReference * type) { + // Is POD of size <= 32 bytes: + switch (type->eTypeClass) { + default: + return true; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + return false; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * t = NULL; + TYPELIB_DANGER_GET(&t, type); + bool b = t->nSize <= 32 && isPodStruct( + reinterpret_cast< typelib_CompoundTypeDescription * >(t)); + TYPELIB_DANGER_RELEASE(t); + return b; + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.hxx new file mode 100644 index 000000000000..f9741a8898a5 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_ISDIRECTRETURNTYPE_x +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_ISDIRECTRETURNTYPE_x + +#include "sal/config.h" + +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { + +bool isDirectReturnType(typelib_TypeDescriptionReference * type); + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/makefile.mk b/bridges/source/cpp_uno/cc5_solaris_sparc64/makefile.mk new file mode 100644 index 000000000000..ec64b1db49dd --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ := ..$/..$/.. +PRJNAME := bridges +TARGET := sunpro5_uno +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk + +.IF "$(COM)" == "C52" && "$(CPU)" == "U" + +SHL1TARGET = $(TARGET) +SHL1OBJS = \ + $(SLO)$/callvirtualmethod.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/exceptions.obj \ + $(SLO)$/fp.obj \ + $(SLO)$/isdirectreturntype.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/vtableslotcall.obj +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib +SHL1STDLIBS = $(CPPULIB) $(SALLIB) +SHL1RPATH = URELIB +SHL1VERSIONMAP = ..$/..$/bridge_exports.map +SHL1IMPLIB= i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.ENDIF + +.INCLUDE: target.mk + +$(SLO)$/%.obj: %.s + CC -m64 -KPIC -c -o $(SLO)$/$(@:b).o $< + touch $@ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/uno2cpp.cxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/uno2cpp.cxx new file mode 100644 index 000000000000..e6646dca42a1 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/uno2cpp.cxx @@ -0,0 +1,512 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" +#include "sal/config.h" + +#include <algorithm> +#include <cstddef> +#include <cstring> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/genfunc.hxx" +#include "osl/diagnose.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/alloca.h" +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "uno/any2.h" +#include "uno/data.h" + +#include "callvirtualmethod.hxx" +#include "exceptions.hxx" +#include "fp.hxx" +#include "isdirectreturntype.hxx" + +namespace { + +namespace css = com::sun::star; + +void storeFpRegsToStruct(typelib_TypeDescription * type, void * data) { + for (typelib_CompoundTypeDescription * t = + reinterpret_cast< typelib_CompoundTypeDescription * >(type); + t != NULL; t = t->pBaseTypeDescription) + { + for (sal_Int32 i = 0; i < t->nMembers; ++i) { + switch (t->ppTypeRefs[i]->eTypeClass) { + case typelib_TypeClass_FLOAT: + switch (t->pMemberOffsets[i]) { + case 0: + fp_storef0(reinterpret_cast< float * >(data)); + break; + case 4: + fp_storef1(reinterpret_cast< float * >(data) + 1); + break; + case 8: + fp_storef2(reinterpret_cast< float * >(data) + 2); + break; + case 12: + fp_storef3(reinterpret_cast< float * >(data) + 3); + break; + case 16: + fp_storef4(reinterpret_cast< float * >(data) + 4); + break; + case 20: + fp_storef5(reinterpret_cast< float * >(data) + 5); + break; + case 24: + fp_storef6(reinterpret_cast< float * >(data) + 6); + break; + case 28: + fp_storef7(reinterpret_cast< float * >(data) + 7); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_DOUBLE: + switch (t->pMemberOffsets[i]) { + case 0: + fp_stored0(reinterpret_cast< double * >(data)); + break; + case 8: + fp_stored2(reinterpret_cast< double * >(data) + 1); + break; + case 16: + fp_stored4(reinterpret_cast< double * >(data) + 2); + break; + case 24: + fp_stored6(reinterpret_cast< double * >(data) + 3); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); + storeFpRegsToStruct(td, data); + TYPELIB_DANGER_RELEASE(td); + break; + } + } + } + } +} + +void call( + bridges::cpp_uno::shared::UnoInterfaceProxy * proxy, + bridges::cpp_uno::shared::VtableSlot slot, + typelib_TypeDescriptionReference * returnType, sal_Int32 count, + typelib_MethodParameter * parameters, void * returnValue, void ** arguments, + uno_Any ** exception) +{ + bool directRet = bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + returnType); + long * stack = static_cast< long * >( + alloca( + std::max< sal_Int32 >(count + (directRet ? 1 : 2), 4) * + sizeof (long))); + sal_Int32 sp = 0; + typelib_TypeDescription * rtd = NULL; + TYPELIB_DANGER_GET(&rtd, returnType); + bool retconv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd); + OSL_ASSERT(!(directRet && retconv)); + void * ret; + if (!directRet) { + ret = retconv ? alloca(rtd->nSize) : returnValue; + stack[sp++] = reinterpret_cast< long >(ret); + } + unsigned long ** thisPtr = reinterpret_cast< unsigned long ** >( + proxy->getCppI()) + slot.offset; + stack[sp++] = reinterpret_cast< long >(thisPtr); + void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); + typelib_TypeDescription ** ptds = + static_cast< typelib_TypeDescription ** >( + alloca(count * sizeof (typelib_TypeDescription *))); + for (sal_Int32 i = 0; i < count; ++i) { + if (!parameters[i].bOut && + bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) + { + cppArgs[i] = NULL; + switch (parameters[i].pTypeRef->eTypeClass) { + case typelib_TypeClass_BOOLEAN: + stack[sp] = *static_cast< sal_Bool * >(arguments[i]); + break; + case typelib_TypeClass_BYTE: + stack[sp] = *static_cast< sal_Int8 * >(arguments[i]); + break; + case typelib_TypeClass_SHORT: + stack[sp] = *static_cast< sal_Int16 * >(arguments[i]); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + stack[sp] = *static_cast< sal_uInt16 * >(arguments[i]); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_ENUM: + stack[sp] = *static_cast< sal_Int32 * >(arguments[i]); + break; + case typelib_TypeClass_UNSIGNED_LONG: + stack[sp] = *static_cast< sal_uInt32 * >(arguments[i]); + break; + case typelib_TypeClass_HYPER: + stack[sp] = *static_cast< sal_Int64 * >(arguments[i]); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + stack[sp] = *static_cast< sal_uInt64 * >(arguments[i]); + break; + case typelib_TypeClass_FLOAT: + { + float * f = static_cast< float * >(arguments[i]); + switch (sp) { + case 1: + fp_loadf3(f); + break; + case 2: + fp_loadf5(f); + break; + case 3: + fp_loadf7(f); + break; + case 4: + fp_loadf9(f); + break; + case 5: + fp_loadf11(f); + break; + case 6: + fp_loadf13(f); + break; + case 7: + fp_loadf15(f); + break; + case 8: + fp_loadf17(f); + break; + case 9: + fp_loadf19(f); + break; + case 10: + fp_loadf21(f); + break; + case 11: + fp_loadf23(f); + break; + case 12: + fp_loadf25(f); + break; + case 13: + fp_loadf27(f); + break; + case 14: + fp_loadf29(f); + break; + case 15: + fp_loadf31(f); + break; + default: + reinterpret_cast< float * >(stack + sp)[1] = *f; + break; + } + break; + } + case typelib_TypeClass_DOUBLE: + { + double * d = static_cast< double * >(arguments[i]); + switch (sp) { + case 1: + fp_loadd2(d); + break; + case 2: + fp_loadd4(d); + break; + case 3: + fp_loadd6(d); + break; + case 4: + fp_loadd8(d); + break; + case 5: + fp_loadd10(d); + break; + case 6: + fp_loadd12(d); + break; + case 7: + fp_loadd14(d); + break; + case 8: + fp_loadd16(d); + break; + case 9: + fp_loadd18(d); + break; + case 10: + fp_loadd20(d); + break; + case 11: + fp_loadd22(d); + break; + case 12: + fp_loadd24(d); + break; + case 13: + fp_loadd26(d); + break; + case 14: + fp_loadd28(d); + break; + case 15: + fp_loadd30(d); + break; + default: + *reinterpret_cast< double * >(stack + sp) = *d; + break; + } + break; + } + case typelib_TypeClass_CHAR: + stack[sp] = *static_cast< sal_Unicode * >(arguments[i]); + break; + default: + OSL_ASSERT(false); + break; + } + } else { + typelib_TypeDescription * ptd = NULL; + TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); + if (!parameters[i].bIn) { + cppArgs[i] = alloca(ptd->nSize); + uno_constructData(cppArgs[i], ptd); + ptds[i] = ptd; + *reinterpret_cast< void ** >(stack + sp) = cppArgs[i]; + } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { + cppArgs[i] = alloca(ptd->nSize); + uno_copyAndConvertData( + cppArgs[i], arguments[i], ptd, + proxy->getBridge()->getUno2Cpp()); + ptds[i] = ptd; + *reinterpret_cast< void ** >(stack + sp) = cppArgs[i]; + } else { + cppArgs[i] = NULL; + *reinterpret_cast< void ** >(stack + sp) = arguments[i]; + TYPELIB_DANGER_RELEASE(ptd); + } + } + ++sp; + } + try { + callVirtualMethod( + (*thisPtr)[slot.index + 2], stack, + std::max< sal_Int32 >(sp - 6, 0) * sizeof (long)); + } catch (css::uno::Exception &) { + void * exc = __Crun::ex_get(); + char const * name = __Cimpl::ex_name(); + bridges::cpp_uno::cc5_solaris_sparc64::fillUnoException( + exc, name, *exception, proxy->getBridge()->getCpp2Uno()); + for (sal_Int32 i = 0; i < count; ++i) { + if (cppArgs[i] != NULL) { + uno_destructData( + cppArgs[i], ptds[i], + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + TYPELIB_DANGER_RELEASE(ptds[i]); + } + } + TYPELIB_DANGER_RELEASE(rtd); + return; + } + *exception = NULL; + for (sal_Int32 i = 0; i < count; ++i) { + if (cppArgs[i] != NULL) { + if (parameters[i].bOut) { + if (parameters[i].bIn) { + uno_destructData(arguments[i], ptds[i], NULL); + } + uno_copyAndConvertData( + arguments[i], cppArgs[i], ptds[i], + proxy->getBridge()->getCpp2Uno()); + } + uno_destructData( + cppArgs[i], ptds[i], + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + TYPELIB_DANGER_RELEASE(ptds[i]); + } + } + if (directRet) { + switch (rtd->eTypeClass) { + case typelib_TypeClass_FLOAT: + fp_storef0(reinterpret_cast< float * >(returnValue)); + break; + case typelib_TypeClass_DOUBLE: + fp_stored0(reinterpret_cast< double * >(returnValue)); + break; + case typelib_TypeClass_STRUCT: + storeFpRegsToStruct(rtd, stack); + // fall through + case typelib_TypeClass_ANY: + std::memcpy(returnValue, stack, rtd->nSize); + break; + default: + OSL_ASSERT(rtd->nSize <= 8); + std::memcpy( + returnValue, + reinterpret_cast< char * >(stack) + (8 - rtd->nSize), + rtd->nSize); + break; + } + } else if (retconv) { + uno_copyAndConvertData( + returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno()); + uno_destructData( + ret, rtd, + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + } + TYPELIB_DANGER_RELEASE(rtd); +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException) +{ + bridges::cpp_uno::shared::UnoInterfaceProxy * proxy = + static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + switch (pMemberDescr->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot slot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn != NULL) { + // Getter: + call( + proxy, slot, + (reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr)->pAttributeTypeRef), + 0, NULL, pReturn, pArgs, ppException); + } else { + // Setter: + typelib_MethodParameter param = { + NULL, + (reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr)->pAttributeTypeRef), + true, false }; + typelib_TypeDescriptionReference * rtd = NULL; + typelib_typedescriptionreference_new( + &rtd, typelib_TypeClass_VOID, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")).pData); + slot.index += 1; + call(proxy, slot, rtd, 1, ¶m, pReturn, pArgs, ppException); + typelib_typedescriptionreference_release(rtd); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot slot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (slot.index) { + case 1: + pUnoI->acquire(pUnoI); + *ppException = NULL; + break; + case 2: + pUnoI->release(pUnoI); + *ppException = NULL; + break; + case 0: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET( + &td, + reinterpret_cast< css::uno::Type * >( + pArgs[0])->getTypeLibType()); + if (td != NULL) { + uno_Interface * ifc = NULL; + proxy->pBridge->getUnoEnv()->getRegisteredInterface( + proxy->pBridge->getUnoEnv(), + reinterpret_cast< void ** >(&ifc), + proxy->oid.pData, + (reinterpret_cast< + typelib_InterfaceTypeDescription * >(td))); + if (ifc != NULL) { + uno_any_construct( + reinterpret_cast< uno_Any * >(pReturn), + &ifc, td, NULL); + ifc->release(ifc); + TYPELIB_DANGER_RELEASE(td); + *ppException = NULL; + break; + } + TYPELIB_DANGER_RELEASE(td); + } + } // fall through + default: + call( + proxy, slot, + (reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr)->pReturnTypeRef), + (reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr)->nParams), + (reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr)->pParams), + pReturn, pArgs, ppException); + } + break; + } + default: + OSL_ASSERT(false); + break; + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.hxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.hxx new file mode 100644 index 000000000000..c63f674c1549 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_VTABLESLOTCALL_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_CC5_SOLARIS_SPARC64_VTABLESLOTCALL_HXX + +#include "sal/config.h" + +extern "C" void vtableSlotCall(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.s b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.s new file mode 100644 index 000000000000..01a22da74fff --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.s @@ -0,0 +1,51 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +.global vtableCall + +.global vtableSlotCall +.align 8 +vtableSlotCall: + ! save %sp, -176, %sp already done in code snippet + stx %i0, [%fp + 2047 + 128] + stx %i1, [%fp + 2047 + 136] + stx %i2, [%fp + 2047 + 144] + stx %i3, [%fp + 2047 + 152] + stx %i4, [%fp + 2047 + 160] + stx %i5, [%fp + 2047 + 168] + ! %o0: functionIndex, stored by code snippet + ! %o1: vtableOffset, stored by code snippet + call vtableCall + add %fp, 2047 + 128, %o2 + ldx [%fp + 2047 + 128], %i0 + ldx [%fp + 2047 + 136], %i1 + ldx [%fp + 2047 + 144], %i2 + ldx [%fp + 2047 + 152], %i3 + ret + restore +.size vtableSlotCall, . - vtableSlotCall +.type vtableSlotCall, #function diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx new file mode 100644 index 000000000000..b343edee7048 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx @@ -0,0 +1,660 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include <string.h> + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, double * fpreg, void ** ovrflw, + sal_uInt64 * pRegisterReturn /* space for register return */ ) +{ + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [remainder of params] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + sal_Int32 ng = 0; + sal_Int32 nf = 0; + + ovrflw -= ppc::MAX_GPR_REGS; + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via ptr (pCppReturn) + { + pCppReturn = *gpreg; + ++gpreg; + ++ng; + ++ovrflw; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? __builtin_alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + ++gpreg; + ++ng; + ++ovrflw; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)__builtin_alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + if (ng < ppc::MAX_GPR_REGS) + { + *ovrflw = *gpreg++; + ++ng; + } + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-1)); + ++ovrflw; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (ng < ppc::MAX_GPR_REGS) + { + *ovrflw = *gpreg++; + ++ng; + } + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-2)); + ++ovrflw; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + for (int i = 0; i < 2; ++i) + { + if (ng < ppc::MAX_GPR_REGS) + { + *ovrflw = *gpreg++; + ++ng; + } + ++ovrflw; + } + break; + case typelib_TypeClass_DOUBLE: + if (nf < ppc::MAX_SSE_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; + ++fpreg; + ++nf; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + } + if (ng < ppc::MAX_GPR_REGS) + { + ng+=2; + gpreg+=2; + } + ovrflw+=2; + break; + case typelib_TypeClass_FLOAT: + if (nf < ppc::MAX_SSE_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; + ++fpreg; + ++nf; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + } + if (ng < ppc::MAX_GPR_REGS) + { + ++gpreg; + ++ng; + } + ++ovrflw; + break; + default: + if (ng < ppc::MAX_GPR_REGS) + { + *ovrflw = *gpreg++; + ++ng; + } + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ++ovrflw; + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + void *pCppStack; //temporary stack pointer + + if (ng < ppc::MAX_GPR_REGS) + { + *ovrflw = *gpreg++; + ++ng; + } + pCppArgs[nPos] = pCppStack = *ovrflw++; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** gpreg, double * fpreg, void ** ovrflw, + sal_uInt64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (in space allocated for all params properly aligned)] + + void * pThis; + if( nFunctionIndex & 0x8000 ) + { + nFunctionIndex &= 0x7fff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static sal_uInt64 cpp_vtable_call(sal_Int32 r3, sal_Int32 r4, sal_Int32 r5, + sal_Int32 r6, sal_Int32 r7, sal_Int32 r8, sal_Int32 r9, + sal_Int32 r10, sal_Int32 firstonstack) +{ + volatile unsigned long nOffsetAndIndex; + + __asm__ __volatile__( + "mr %0, 11\n\t" + : "=r" (nOffsetAndIndex) : ); + + sal_Int32 nVtableOffset = (nOffsetAndIndex >> 16); + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFF); + + void ** ovrflw = (void**)&firstonstack; + + sal_Int32 gpreg[ppc::MAX_GPR_REGS]; + gpreg[0] = r3; + gpreg[1] = r4; + gpreg[2] = r5; + gpreg[3] = r6; + gpreg[4] = r7; + gpreg[5] = r8; + gpreg[6] = r9; + gpreg[7] = r10; + + double fpreg[ppc::MAX_SSE_REGS]; + register double d0 asm("fr1"); fpreg[0] = d0; + register double d1 asm("fr2"); fpreg[1] = d1; + register double d2 asm("fr3"); fpreg[2] = d2; + register double d3 asm("fr4"); fpreg[3] = d3; + register double d4 asm("fr5"); fpreg[4] = d4; + register double d5 asm("fr6"); fpreg[5] = d5; + register double d6 asm("fr7"); fpreg[6] = d6; + register double d7 asm("fr8"); fpreg[7] = d7; + register double d8 asm("fr9"); fpreg[8] = d8; + register double d9 asm("fr10"); fpreg[9] = d9; + register double d10 asm("fr11"); fpreg[10] = d10; + register double d11 asm("fr12"); fpreg[11] = d11; + register double d12 asm("fr13"); fpreg[12] = d12; + +#if OSL_DEBUG_LEVEL > 2 + for(int i = 0; i < 8; ++i) + { + fprintf(stderr, "general reg %d is %x\n", i, gpreg[i]); + } + for(int i = 0; i < 13; ++i) + { + fprintf(stderr, "sse reg %d is %f\n", i, fpreg[i]); + fprintf(stderr, "sse reg %d is %llx\n", i, fpreg[i]); + } + for(int i = -8; i < 8; ++i) + { + fprintf(stderr, "overflow arg %d is %x\n", i, ovrflw[i]); + } +#endif + sal_uInt64 nRegReturn=0; + + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, fpreg, ovrflw, &nRegReturn ); + + sal_uInt32 *pRegReturn = (sal_uInt32*)&nRegReturn; + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + pRegReturn[0] = (sal_uInt32)(*(char *)pRegReturn); + break; + case typelib_TypeClass_BYTE: + pRegReturn[0] = (sal_Int32)(*(unsigned char *)pRegReturn); + break; + case typelib_TypeClass_SHORT: + pRegReturn[0] = (sal_Int32)(*(short *)pRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + pRegReturn[0] = (sal_uInt32)(*(unsigned short *)pRegReturn); + break; + case typelib_TypeClass_FLOAT: + __asm__("lfs 1,%0\n\t" : : "m"(*((float*)&nRegReturn))); + break; + case typelib_TypeClass_DOUBLE: + __asm__("lfd 1,%0\n\t" : : "m"(*((double*)&nRegReturn))); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + break; + default: + pRegReturn[0] = (sal_uInt32)(*(unsigned int*)pRegReturn); + break; + } + return nRegReturn; +} + + +int const codeSnippetSize = 3 * sizeof(void*); + +unsigned char * codeSnippet( unsigned char * code, sal_Int16 functionIndex, + sal_Int16 vtableOffset, bool simpleRetType ) +{ + sal_uInt32 nOffsetAndIndex = ( ( vtableOffset ) << 16 ) | (functionIndex ); + if (! simpleRetType ) + nOffsetAndIndex |= 0x8000; + + void **raw = (void**)&code[0]; + memcpy(raw, (char*)cpp_vtable_call, 2 * sizeof(void*)); + raw[2] = (void*)nOffsetAndIndex; + + return (code + codeSnippetSize); +} + +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) +{ + int const lineSize = 32; + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("sync" : : : "memory"); + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("isync" : : : "memory"); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/except.cxx b/bridges/source/cpp_uno/gcc3_aix_powerpc/except.cxx new file mode 100644 index 000000000000..2086ef7e7bba --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/except.cxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" +#include <string.h> + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#ifdef DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#ifdef DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iiFind( m_generatedRttis.find( unoName ) ); + if (iiFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#ifdef DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iiFind->second; + } + } + } + else + { + rtti = iFind->second; + } + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/makefile.mk b/bridges/source/cpp_uno/gcc3_aix_powerpc/makefile.mk new file mode 100644 index 000000000000..48c51c138d4d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCAIXPgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS= $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) \ + -ldl + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/share.hxx b/bridges/source/cpp_uno/gcc3_aix_powerpc/share.hxx new file mode 100644 index 000000000000..e3f8370d501f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/share.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace ppc +{ + enum ppclimits { MAX_GPR_REGS = 8, MAX_SSE_REGS = 13 }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_aix_powerpc/uno2cpp.cxx new file mode 100644 index 000000000000..dcb4793e98d3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/uno2cpp.cxx @@ -0,0 +1,499 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sys/types.h> +#include <sys/malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +void MapReturn(sal_uInt32 r3, sal_uInt32 r4, double dret, typelib_TypeClass eReturnType, void *pRegisterReturn) +{ + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = r4; + // fall through on purpose + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = r3; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)r3; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)r3; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = (float)dret; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + default: + break; + } +} + +#define DISPLACEMENT -2 + +static void callVirtualMethod( + void * pThis, + sal_uInt32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_uInt32 * pStack, + sal_uInt32 nStack, + double *pFPR, + sal_uInt32 nFPR) +{ + sal_uInt32 nStackWords = nStack; + if (nStackWords < ppc::MAX_GPR_REGS) + nStackWords = 0; + else + nStackWords-=ppc::MAX_GPR_REGS; + if (nStackWords) + nStackWords = ( nStackWords + 1) & ~1; + sal_uInt32 *stack = (sal_uInt32*)__builtin_alloca( nStackWords * sizeof(sal_uInt32) ); + memcpy(stack+DISPLACEMENT, pStack+ppc::MAX_GPR_REGS, nStack * sizeof(sal_uInt32)); + + // Get pointer to method + sal_uInt32 pMethod = *((sal_uInt32 *)pThis); + pMethod += 4 * nVtableIndex; + pMethod = *((sal_uInt32 *)pMethod); + + typedef void (* FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + register double d0 asm("fr1"); d0 = pFPR[0]; + register double d1 asm("fr2"); d1 = pFPR[1]; + register double d2 asm("fr3"); d2 = pFPR[2]; + register double d3 asm("fr4"); d3 = pFPR[3]; + register double d4 asm("fr5"); d4 = pFPR[4]; + register double d5 asm("fr6"); d5 = pFPR[5]; + register double d6 asm("fr7"); d6 = pFPR[6]; + register double d7 asm("fr8"); d7 = pFPR[7]; + register double d8 asm("fr9"); d8 = pFPR[8]; + register double d9 asm("fr10"); d9 = pFPR[9]; + register double d10 asm("fr11"); d10 = pFPR[10]; + register double d11 asm("fr12"); d11 = pFPR[11]; + register double d12 asm("fr13"); d12 = pFPR[12]; + + (*pFunc)(pStack[0], pStack[1], pStack[2], pStack[3], pStack[4], pStack[5], pStack[6], pStack[7]); + + register sal_uInt32 r3 asm("r3"); + register sal_uInt32 r4 asm("r4"); + MapReturn(r3, r4, d0, eReturnType, pRegisterReturn); +} + +#define INSERT_INT32(pSV, pDS) \ +{ \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>(pSV); \ +} + +#define INSERT_INT16(pSV, pDS) \ +{ \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>(pSV); \ +} + +#define INSERT_INT8(pSV, pDS) \ +{ \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>(pSV); \ +} + +#define INSERT_FLOAT(pSV, nr, pFPR, pDS) \ +{ \ + if (nr < ppc::MAX_SSE_REGS) \ + { \ + sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr++]); \ + pDouble[0] = *reinterpret_cast<sal_uInt32 *>(pSV); \ + } \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>(pSV); \ +} + +#define INSERT_DOUBLE(pSV, nr, pFPR, pDS) \ +{ \ + if (nr < ppc::MAX_SSE_REGS) \ + { \ + pFPR[nr++] = *reinterpret_cast<double *>(pSV); \ + } \ + *pDS++ = reinterpret_cast<sal_uInt32 *>(pSV)[1]; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>(pSV)[0]; \ +} + +#define INSERT_INT64(pSV, pDS) \ +{ \ + INSERT_INT32(pSV, pDS) \ + INSERT_INT32(((sal_uInt32*)pSV)+1, pDS) \ +} +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt32 * pStack = (sal_uInt32*)__builtin_alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + sal_uInt32 * pStackStart = pStack; + + double pFPR[ppc::MAX_SSE_REGS]; + sal_uInt32 nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? __builtin_alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + INSERT_INT32(&pCppReturn, pStack); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset; + INSERT_INT32(&pAdjustedThisPtr, pStack); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)__builtin_alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32(pCppArgs[nPos], pStack); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16(pCppArgs[nPos], pStack); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8(pCppArgs[nPos], pStack); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT(pCppArgs[nPos], nFPR, pFPR, pStack); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE(pCppArgs[nPos], nFPR, pFPR, pStack); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64(pCppArgs[nPos], pStack); + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT32(&(pCppArgs[nPos]), pStack); + } + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, + pStackStart, (pStack - pStackStart), pFPR, nFPR ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * > (pUnoI); + // typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx new file mode 100644 index 000000000000..110013b33b0c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx @@ -0,0 +1,543 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include "boost/static_assert.hpp" +#include <stdio.h> + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +void cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + void * pReturnValue ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + // xxx todo: test PolyStructy<STRUCT<long>> foo() + if (CPPU_CURRENT_NAMESPACE::isSimpleReturnType( pReturnTypeDescr )) + { + pUnoReturn = pReturnValue; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + if (pReturnValue != pCppReturn) { + // complex return ptr is set to eax if return value + // is not transferred via eax[/edx]: + *static_cast< void ** >(pReturnValue) = pCppReturn; + } + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } +} + + +//================================================================================================== +extern "C" void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack, + void * pReturnValue ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "%p %p %p pThis=%p, pCppI=%p, function index=%d, vtable offset=%d\n", pCallStack[0], pCallStack[1], pCallStack[2], pThis, pCppI, nFunctionIndex, nVtableOffset ); +#endif + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "name=%s\n", rtl::OUStringToOString(pTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_UTF8).getStr() ); +#endif + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "calling %s\n", rtl::OUStringToOString(aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_UTF8).getStr()); +#endif + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pReturnValue ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pReturnValue ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *static_cast< void ** >(pReturnValue) = pCallStack[1]; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pReturnValue ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + } + } +} + +//================================================================================================== + +extern "C" { +extern int nFunIndexes, nVtableOffsets; +extern unsigned char **codeSnippets; +} + +unsigned char * codeSnippet( + sal_Int32 functionIndex, sal_Int32 vtableOffset, +#ifdef __arm + bool bHasHiddenParam +#else + typelib_TypeDescriptionReference * pReturnTypeRef +#endif + ) +{ + OSL_ASSERT(functionIndex < nFunIndexes); + if (!(functionIndex < nFunIndexes)) + return NULL; + + OSL_ASSERT(vtableOffset < nVtableOffsets); + if (!(vtableOffset < nVtableOffsets)) + return NULL; + +#ifdef __arm + return codeSnippets[functionIndex*nVtableOffsets*2 + vtableOffset*2 + bHasHiddenParam]; +#else + enum { General, Void, Hyper, Float, Double, Class } exec; + int flag = 0; + if (pReturnTypeRef == 0) { + exec = Void; + } + else { + switch (pReturnTypeRef->eTypeClass) { + case typelib_TypeClass_VOID: + exec = Void; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + exec = Hyper; + break; + case typelib_TypeClass_FLOAT: + exec = Float; + break; + case typelib_TypeClass_DOUBLE: + exec = Double; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + bool const bSimpleReturnStruct = + CPPU_CURRENT_NAMESPACE::isSimpleReturnType(pReturnTypeDescr); + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + if (bSimpleReturnStruct && nRetSize <= 8) { + exec = General; // fills eax + if (nRetSize > 4) + exec = Hyper; // fills eax/edx + break; + } + } + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_ANY: + flag = 1; + exec = Class; + break; + default: + exec = General; + break; + } + } + + return codeSnippets[functionIndex*nVtableOffsets*6*2 + vtableOffset*6*2 + exec*2 + flag]; +#endif + +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return 0; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: +#ifdef __arm + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member ); +#endif + // Getter: + (s++)->fn = codeSnippet( + functionOffset++, vtableOffset, +#ifdef __arm + arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) +#else + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef +#endif + ); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = codeSnippet( + functionOffset++, vtableOffset, +#ifdef __arm + false +#else + 0 /* indicates VOID */ +#endif + ); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: +#ifdef __arm + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >(member); +#endif + (s++)->fn = codeSnippet( + functionOffset++, vtableOffset, +#ifdef __arm + arm::return_in_hidden_param(pMethodTD->pReturnTypeRef) +#else + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef +#endif + ); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx new file mode 100644 index 000000000000..a14bc8b9aec0 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) ); + if (iFind2 == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind2->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl new file mode 100755 index 000000000000..4fe9f2fe4021 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl -w + +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License or as specified alternatively below. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Tor Lillqvist <tml@iki.fi> +# Portions created by the Initial Developer are Copyright (C) 2011 the +# Initial Developer. All Rights Reserved. +# +# For minor contributions see the git repository. +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. + +my $nFunIndexes = 5; +my $nVtableOffsets = 1; + +sub gen_arm ($$) +{ + my ($funIndex, $vtableOffset) = @_; + printf ("codeSnippet%08x%d:\n", $funIndex, $vtableOffset); + printf ("\tmov ip, pc\n"); + printf ("\tldr pc, [pc, #4]\n"); + printf ("\t.long %#08x\n", $funIndex); + printf ("\t.long %d\n", $vtableOffset); + printf ("\t.long _privateSnippetExecutor\n"); +} + +sub gen_x86 ($$$) +{ + my ($funIndex, $vtableOffset, $executor) = @_; + printf ("codeSnippet%08x%d%s:\n", $funIndex, $vtableOffset, $executor); + printf ("\tmovl %#08x, %%eax\n", $funIndex); + printf ("\tmovl \$%d, %%edx\n", $vtableOffset); + printf ("\tjmp _privateSnippetExecutor%s\n", $executor); +} + +printf ("\t.text\n"); + +printf ("#ifdef __arm\n"); +printf ("\t.align 4\n"); + +foreach my $funIndex (0 .. $nFunIndexes-1) +{ + foreach my $vtableOffset (0 .. $nVtableOffsets-1) + { + gen_arm ($funIndex, $vtableOffset); + gen_arm ($funIndex|0x80000000, $vtableOffset); + } +} + +printf ("#else\n"); + +foreach my $funIndex (0 .. $nFunIndexes-1) +{ + foreach my $vtableOffset (0 .. $nVtableOffsets-1) + { + foreach my $executor ('General', 'Void', 'Hyper', 'Float', 'Double', 'Class') + { + gen_x86 ($funIndex, $vtableOffset, $executor); + gen_x86 ($funIndex|0x80000000, $vtableOffset, $executor); + } + } +} + +printf ("#endif\n"); + +printf ("\t.globl _nFunIndexes\n"); +printf ("_nFunIndexes:\n"); +printf ("\t.long %d\n", $nFunIndexes); + +printf ("\t.globl _nVtableOffsets\n"); +printf ("_nVtableOffsets:\n"); +printf ("\t.long %d\n", $nVtableOffsets); + +printf ("\t.globl _codeSnippets\n"); +printf ("_codeSnippets:\n"); + +foreach my $funIndex (0 .. $nFunIndexes-1) +{ + foreach my $vtableOffset (0 .. $nVtableOffsets-1) + { + printf ("#ifdef __arm\n"); + printf ("\t.long codeSnippet%08x%d\n", $funIndex, $vtableOffset); + printf ("\t.long codeSnippet%08x%d\n", $funIndex|0x80000000, $vtableOffset); + printf ("#else\n"); + foreach my $executor ('General', 'Void', 'Hyper', 'Float', 'Double', 'Class') + { + printf ("\t.long codeSnippet%08x%d%s\n", $funIndex, $vtableOffset, $executor); + printf ("\t.long codeSnippet%08x%d%s\n", $funIndex|0x80000000, $vtableOffset, $executor); + } + printf ("#endif\n"); + } +} diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/helper.S b/bridges/source/cpp_uno/gcc3_ios_arm/helper.S new file mode 100644 index 000000000000..0bd718b9b660 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/helper.S @@ -0,0 +1,353 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifdef __arm +@ ARM support code for LibreOffice C++/UNO bridging +@ +@ Written by Peter Naulls <peter@chocky.org> +@ Modified by Caolan McNamara <caolanm@redhat.com> +@ Fixed by Michael Casadevall <mcasadevall@kubuntu.org> +@ Modified for iOS by Tor Lillqvist <tml@iki.fi> + + .file "helper.S" + .text + .align 4 + .globl privateSnippetExecutor + +privateSnippetExecutor: + stmfd sp!, {r0-r3} @ follow other parameters on stack + mov r0, ip @ r0 points to functionoffset/vtable + mov r1, sp @ r1 points to this and params + @ (see cpp2uno.cxx:codeSnippet()) + stmfd sp!, {r4,lr} @ save return address + @ (r4 pushed to preserve stack alignment) + bl cpp_vtable_call + + add sp, sp, #4 @ no need to restore r4 (we didn't touch it) + ldr pc, [sp], #20 @ return, discarding function arguments + +#else + .text + +.align 1, 0x90 +.globl _privateSnippetExecutorGeneral +_privateSnippetExecutorGeneral: +LFBg: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIg0: + movl %esp,%ebp +LCFIg1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 32bit returnValue + leave + ret +LFEg: + .long .-_privateSnippetExecutorGeneral + +.align 1, 0x90 +.globl _privateSnippetExecutorVoid +_privateSnippetExecutorVoid: +LFBv: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIv0: + movl %esp,%ebp +LCFIv1: + sub $8,%esp # padding + pushl $0 # 32bit null pointer (returnValue not used) + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + leave + ret +LFEv: + .long .-_privateSnippetExecutorVoid + +.align 1, 0x90 +.globl _privateSnippetExecutorHyper +_privateSnippetExecutorHyper: +LFBh: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIh0: + movl %esp,%ebp +LCFIh1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 64bit returnValue, lower half + movl 20(%esp),%edx # 64bit returnValue, upper half + leave + ret +LFEh: + .long .-_privateSnippetExecutorHyper + +.align 1, 0x90 +.globl _privateSnippetExecutorFloat +_privateSnippetExecutorFloat: +LFBf: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIf0: + movl %esp,%ebp +LCFIf1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + flds 16(%esp) # 32bit returnValue + leave + ret +LFEf: + .long .-_privateSnippetExecutorFloat + +.align 1, 0x90 +.globl _privateSnippetExecutorDouble +_privateSnippetExecutorDouble: +LFBd: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFId0: + movl %esp,%ebp +LCFId1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + fldl 16(%esp) # 64bit returnValue + leave + ret +LFEd: + .long .-_privateSnippetExecutorDouble + +.align 1, 0x90 +.globl _privateSnippetExecutorClass +_privateSnippetExecutorClass: +LFBc: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIc0: + movl %esp,%ebp +LCFIc1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 32bit returnValue + leave + ret $4 +LFEc: + .long .-_privateSnippetExecutorClass + + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame1: + .set L$set$frame1,LECIE1-LSCIE1 + .long L$set$frame1 # length +LSCIE1: + .long 0 # CIE_ID + .byte 1 # version + .ascii "zPR\0" # augmentation + .byte 1 # code_alignment_factor (.uleb128 1) + .byte 0x7c # data_alignment_factor (.sleb128 -4) + .byte 8 # return_address_register + .byte 0x6 # augmentation size 7: + .byte 0x9b # ??? + .long L___gxx_personality_v0$non_lazy_ptr-. + .byte 0x10 + # initial_instructions: + .byte 0x0C # DW_CFA_def_cfa %esp, 4 + .byte 5 + .byte 4 + .byte 0x88 # DW_CFA_offset ret, 1 + .byte 1 + .align 2 +LECIE1: + .globl _privateSnippetExecutorGeneral.eh +_privateSnippetExecutorGeneral.eh: +LSFDEg: + .set L$set$g1,LEFDEg-LASFDEg + .long L$set$g1 # length +LASFDEg: + .long LASFDEg-EH_frame1 # CIE_pointer + .long LFBg-. # initial_location + .long LFEg-LFBg # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIg0-LFBg + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIg1-LCFIg0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEg: + .globl _privateSnippetExecutorVoid.eh +_privateSnippetExecutorVoid.eh: +LSFDEv: + .set L$set$v1,LEFDEv-LASFDEv + .long L$set$v1 # length +LASFDEv: + .long LASFDEv-EH_frame1 # CIE_pointer + .long LFBv-. # initial_location + .long LFEv-LFBv # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIv0-LFBv + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIv1-LCFIv0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEv: + .globl _privateSnippetExecutorHyper.eh +_privateSnippetExecutorHyper.eh: +LSFDEh: + .set L$set$h1,LEFDEh-LASFDEh + .long L$set$h1 # length +LASFDEh: + .long LASFDEh-EH_frame1 # CIE_pointer + .long LFBh-. # initial_location + .long LFEh-LFBh # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIh0-LFBh + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIh1-LCFIh0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEh: + .globl _privateSnippetExecutorFloat.eh +_privateSnippetExecutorFloat.eh: +LSFDEf: + .set L$set$f1,LEFDEf-LASFDEf + .long L$set$f1 # length +LASFDEf: + .long LASFDEf-EH_frame1 # CIE_pointer + .long LFBf-. # initial_location + .long LFEf-LFBf # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIf0-LFBf + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIf1-LCFIf0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEf: + .globl _privateSnippetExecutorDouble.eh +_privateSnippetExecutorDouble.eh: +LSFDEd: + .set L$set$d1,LEFDEd-LASFDEd + .long L$set$d1 # length +LASFDEd: + .long LASFDEd-EH_frame1 # CIE_pointer + .long LFBd-. # initial_location + .long LFEd-LFBd # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFId0-LFBd + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFId1-LCFId0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEd: + .globl _privateSnippetExecutorClass.eh +_privateSnippetExecutorClass.eh: +LSFDEc: + .set L$set$c1,LEFDEc-LASFDEc + .long L$set$c1 # length +LASFDEc: + .long LASFDEc-EH_frame1 # CIE_pointer + .long LFBc-. # initial_location + .long LFEc-LFBc # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIc0-LFBc + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIc1-LCFIc0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEc: + .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 +L_cpp_vtable_call$stub: + .indirect_symbol _cpp_vtable_call + hlt ; hlt ; hlt ; hlt ; hlt + .section __IMPORT,__pointers,non_lazy_symbol_pointers +L___gxx_personality_v0$non_lazy_ptr: + .indirect_symbol ___gxx_personality_v0 + .long 0 + .constructor + .destructor + .align 1 +#endif diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk b/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk new file mode 100644 index 000000000000..55e6ca75fca7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCIOSRgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/codesnippets.obj \ + $(SLO)$/helper.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib +SHL1RPATH = URELIB + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.S + $(CC) -c -o $(SLO)$/$(@:b).o $< + touch $@ + +codesnippets.S: generate-snippets.pl + $(PERL) generate-snippets.pl >$@ + diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx new file mode 100644 index 000000000000..8b105c0880b3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false); + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx new file mode 100644 index 000000000000..9793f282c679 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx @@ -0,0 +1,500 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + +#ifdef __arm + +#else + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + // stack padding to keep stack aligned: + "shl $2, %%eax\n\t" + "neg %%eax\n\t" + "add %%esp, %%eax\n\t" + "and $0xf, %%eax\n\t" + "sub %%eax, %%esp\n\t" + // copy: + "mov %%edx, %%eax\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + switch( pReturnTypeDescr->eTypeClass ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + default: { + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 8 && nRetSize > 0) { + if (nRetSize > 4) + static_cast<long *>(pRegisterReturn)[1] = edx; + static_cast<long *>(pRegisterReturn)[0] = eax; + } + break; + } + } +#endif +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + bool bSimpleReturn = true; + + if (pReturnTypeDescr) + { + bSimpleReturn = CPPU_CURRENT_NAMESPACE::isSimpleReturnType( + pReturnTypeDescr); + if (bSimpleReturn) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + // complex return via ptr + *(void **)pCppStack = pCppReturn; + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, bSimpleReturn, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "caught C++ exception\n" ); +#endif + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace CPPU_CURRENT_NAMESPACE { +bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive) +{ + if (bridges::cpp_uno::shared::isSimpleType( pTD )) + return true; + // Only structs of exactly 1, 2, 4, or 8 bytes are returned through + // registers, see <http://developer.apple.com/documentation/DeveloperTools/ + // Conceptual/LowLevelABI/Articles/IA32.html>: + if (pTD->eTypeClass == typelib_TypeClass_STRUCT && + (recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8)) + { + typelib_CompoundTypeDescription *const pCompTD = + (typelib_CompoundTypeDescription *) pTD; + for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) { + typelib_TypeDescription * pMemberTD = 0; + TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] ); + bool const b = isSimpleReturnType(pMemberTD, true); + TYPELIB_DANGER_RELEASE( pMemberTD ); + if (! b) + return false; + } + return true; + } + return false; +} +} + +//================================================================================================== + +namespace bridges { namespace cpp_uno { namespace shared { +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx new file mode 100644 index 000000000000..d4f304f77841 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx @@ -0,0 +1,677 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include <stdio.h> + +//Calling Standards: +// "Calling Standard for Alpha Systems" +// (Tru64 UNIX Version 5.1 or higher, August 2000) +//http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_HTML/ARH9MBTE/TITLE.HTM + +using namespace ::com::sun::star::uno; + +namespace +{ +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "as far as cpp2uno_call\n"); +#endif + int nregs = 0; //number of words passed in registers + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + fpreg++; + nregs++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + fpreg++; + nregs++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple type is %d\n", pParamTypeDescr->eTypeClass); +#endif + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + if (nregs < axp::MAX_WORDS_IN_REGS) + { + if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT) + { + float tmp = (float) (*((double *)fpreg)); + (*((float *) fpreg)) = tmp; + } + + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (nregs < axp::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (nregs < axp::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (nregs < axp::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + default: + if (nregs < axp::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex, nregs is %d\n", nregs); +#endif + + void *pCppStack; //temporary stack pointer + + if (nregs < axp::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pCppStack = *gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pCppStack = *ovrflw; + ovrflw++; + } + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of params\n"); +#endif + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//============================================================================ +static typelib_TypeClass cpp_mediate( + sal_uInt64 nOffsetAndIndex, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" ); + + sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32); + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "nVTableOffset, nFunctionIndex are %x %x\n", nVtableOffset, nFunctionIndex); +#endif + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= cpp_mediate () =\nGPR's (%d): ", 6 ); + for ( unsigned int i = 0; i < 6; ++i ) + fprintf( stderr, "0x%lx, ", gpreg[i] ); + fprintf( stderr, "\n"); + fprintf( stderr, "\nFPR's (%d): ", 6 ); + for ( unsigned int i = 0; i < 6; ++i ) + fprintf( stderr, "0x%lx (%f), ", fpreg[i], fpreg[i] ); + fprintf( stderr, "\n"); + } +#endif + + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // _this_ ptr is patched cppu_XInterfaceProxy object + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +long cpp_vtable_call(long r16, long r17, long r18, long r19, long r20, long r21, long firstonstack) +{ + register long r1 asm("$1"); + sal_uInt64 nOffsetAndIndex = r1; + + long sp = (long)&firstonstack; + + sal_uInt64 gpreg[axp::MAX_GPR_REGS]; + gpreg[0] = r16; + gpreg[1] = r17; + gpreg[2] = r18; + gpreg[3] = r19; + gpreg[4] = r20; + gpreg[5] = r21; + + double fpreg[axp::MAX_SSE_REGS]; + register double f16 asm("$f16"); fpreg[0] = f16; + register double f17 asm("$f17"); fpreg[1] = f17; + register double f18 asm("$f18"); fpreg[2] = f18; + register double f19 asm("$f19"); fpreg[3] = f19; + register double f20 asm("$f20"); fpreg[4] = f20; + register double f21 asm("$f21"); fpreg[5] = f21; + + volatile long nRegReturn[1]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "before mediate with %lx\n",nOffsetAndIndex); + fprintf(stderr, "non-doubles are %x %x %x %x %x %x\n", gpreg[0], gpreg[1], gpreg[2], gpreg[3], gpreg[4], gpreg[5]); + fprintf(stderr, "doubles are %f %f %f %f %f %f\n", fpreg[0], fpreg[1], fpreg[2], fpreg[3], fpreg[4], fpreg[5]); +#endif + typelib_TypeClass aType = + cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, (void**)sp, + (sal_Int64*)nRegReturn ); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "after mediate ret is %lx %ld\n", nRegReturn[0], nRegReturn[0]); +#endif + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + nRegReturn[0] = (unsigned long)(*(unsigned char *)nRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + nRegReturn[0] = (unsigned long)(*(unsigned short *)nRegReturn); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + nRegReturn[0] = (unsigned long)(*(unsigned int *)nRegReturn); + break; + case typelib_TypeClass_VOID: + default: + break; + case typelib_TypeClass_FLOAT: + { + double tmp = (double) (*((float *)nRegReturn)); + (*((double *) nRegReturn)) = tmp; + } + //deliberate fall through + case typelib_TypeClass_DOUBLE: + __asm__ ( "ldt $f0,%0\n\t" + : : "m" (*((double*)nRegReturn)) : "$f0"); + break; + } + return nRegReturn[0]; +} + +const int codeSnippetSize = 32; + +unsigned char *codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool simple_ret_type ) +{ + if (! simple_ret_type) + nFunctionIndex |= 0x80000000; + + unsigned char * p = code; + *(unsigned int*)&p[0] = 0x47fb0401; /* mov $27,$1 */ + *(unsigned int*)&p[4] = 0xa43b0010; /* ldq $1,16($27) */ + *(unsigned int*)&p[8] = 0xa77b0018; /* ldq $27,24($27) */ + *(unsigned int*)&p[12] = 0x6bfb0000; /* jmp $31,($27),0 */ + *(unsigned int*)&p[16] = nFunctionIndex; + *(unsigned int*)&p[20] = nVtableOffset; + *(unsigned long*)&p[24] = (unsigned long)cpp_vtable_call; + return (code + codeSnippetSize); +} +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, unsigned char const *) +{ + //http://www.gnu.org/software/lightning/manual/html_node/Standard-functions.html + __asm__ __volatile__("call_pal 0x86"); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/except.cxx b/bridges/source/cpp_uno/gcc3_linux_alpha/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_alpha/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_alpha/makefile.mk new file mode 100644 index 000000000000..5376b395e35f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_alpha/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)" == "GCCLINUXL" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/share.hxx b/bridges/source/cpp_uno/gcc3_linux_alpha/share.hxx new file mode 100644 index 000000000000..d76cbf748db3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_alpha/share.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace axp +{ + enum axplimits { MAX_WORDS_IN_REGS = 6, MAX_GPR_REGS = 6, MAX_SSE_REGS = 6 }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_alpha/uno2cpp.cxx new file mode 100644 index 000000000000..db6d18800c4f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_alpha/uno2cpp.cxx @@ -0,0 +1,534 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(long r0, typelib_TypeClass eTypeClass, sal_uInt64* pRegisterReturn) +{ + register float fret asm("$f0"); + register double dret asm("$f0"); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr,"Mapping Return with %lx %ld %f\n", r0, r0, dret); +#endif + switch (eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pRegisterReturn = r0; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *(unsigned int*)pRegisterReturn = (unsigned int)r0; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)r0; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)r0; + break; + case typelib_TypeClass_FLOAT: + *reinterpret_cast<float *>( pRegisterReturn ) = fret; + break; + case typelib_TypeClass_DOUBLE: + *reinterpret_cast<double *>( pRegisterReturn ) = dret; + break; + default: + break; + } +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of MapReturn with %x\n", pRegisterReturn ? *pRegisterReturn : 0); +#endif +} + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ + { \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + { \ + pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \ + } \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + } + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ + if ( nr < axp::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +namespace +{ +//================================================================================================== +void callVirtualMethod( + void * pThis, sal_Int32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ + // Should not happen, but... + if ( nFPR > axp::MAX_SSE_REGS ) + nFPR = axp::MAX_SSE_REGS; + if ( nGPR > axp::MAX_GPR_REGS ) + nGPR = axp::MAX_GPR_REGS; + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= nStack is %d\n", nStack ); + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( unsigned int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( unsigned int i = 0; i < nFPR; ++i ) + fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn); + } +#endif + + // Load parameters to stack, if necessary + // Stack, if used, must be 8-bytes aligned + sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 ); + memcpy( stack, pStack, nStack * 8 ); + + // To get pointer to method + // a) get the address of the vtable + sal_uInt64 pMethod = *((sal_uInt64 *)pThis); + // b) get the address from the vtable entry at offset + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + switch (nFPR) //deliberate fall through + { + case 6: + asm volatile("ldt $f16,%0" :: "m"(pFPR[5]) : "$f16"); + case 5: + asm volatile("ldt $f17,%0" :: "m"(pFPR[4]) : "$f17"); + case 4: + asm volatile("ldt $f18,%0" :: "m"(pFPR[3]) : "$f18"); + case 3: + asm volatile("ldt $f19,%0" :: "m"(pFPR[2]) : "$f19"); + case 2: + asm volatile("ldt $f20,%0" :: "m"(pFPR[1]) : "$f20"); + case 1: + asm volatile("ldt $f21,%0" :: "m"(pFPR[0]) : "$f21"); + default: + break; + } + + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5]); + register sal_uInt64 r0 __asm__("$0"); + MapReturn(r0, pReturnTypeDescr->eTypeClass, (sal_uInt64*)pRegisterReturn); +} + + +//============================================================================ +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; + + sal_uInt64 pGPR[axp::MAX_GPR_REGS]; + double pFPR[axp::MAX_SSE_REGS]; + sal_uInt32 nRegs = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + INSERT_INT64( &pCppReturn, nRegs, pGPR, pStack ); + } + } + // push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; + + INSERT_INT64( &pAdjustedThisPtr, nRegs, pGPR, pStack ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64( pCppArgs[nPos], nRegs, pGPR, pStack ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32( pCppArgs[nPos], nRegs, pGPR, pStack ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nRegs, pGPR, pStack ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nRegs, pGPR, pStack ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], nRegs, pFPR, pStack ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], nRegs, pFPR, pStack ); + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nRegs, pGPR, pStack ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, + pStackStart, (pStack - pStackStart), + pGPR, nRegs, + pFPR, nRegs ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "unoInterfaceProxyDispatch\n"); +#endif + + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S new file mode 100644 index 000000000000..d5faf15eed6f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S @@ -0,0 +1,38 @@ +@ ARM support code for OpenOffice C++/UNO bridging +@ +@ Written by Peter Naulls <peter@chocky.org> +@ Modified by Caolan McNamara <caolanm@redhat.com> +@ Fixed by Michael Casadevall <mcasadevall@kubuntu.org> + +#ifdef __ARM_EABI__ +# define UNWIND +#else +# define UNWIND @ +#endif + + .file "armhelper.s" + .text + .align 4 + .global privateSnippetExecutor + .type privateSnippetExecutor, %function +privateSnippetExecutor: + UNWIND .fnstart @ start of unwinder entry + + stmfd sp!, {r0-r3} @ follow other parameters on stack + UNWIND .pad #16 @ throw this data away on exception + mov r0, ip @ r0 points to functionoffset/vtable + mov r1, sp @ r1 points to this and params + @ (see cppuno.cxx:codeSnippet()) + stmfd sp!, {r4,lr} @ save return address + @ (r4 pushed to preserve stack alignment) + UNWIND .save {r4,lr} @ restore these regs on exception + + bl cpp_vtable_call(PLT) + + add sp, sp, #4 @ no need to restore r4 (we didn't touch it) + ldr pc, [sp], #20 @ return, discarding function arguments + + UNWIND .fnend @ end of unwinder entry + + .size privateSnippetExecutor, . - privateSnippetExecutor + .section .note.GNU-stack,"",%progbits diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx new file mode 100644 index 000000000000..737824c70498 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx @@ -0,0 +1,554 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <boost/unordered_map.hpp> + +#include <rtl/alloc.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include <dlfcn.h> + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + + static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy* pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + // pCallStack: ret, [return ptr], this, params + char * pTopStack = (char *)(pCallStack + 0); + char * pCppStack = pTopStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + // complex return ptr: if != 0 && != pUnoReturn, reconversion need + void * pCppReturn = 0; + + if (pReturnTypeDescr) + { + if (!arm::return_in_hidden_param(pReturnTypeRef)) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), + "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion + // cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = + (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && + bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +#ifdef __ARM_EABI__ + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + if ((pCppStack - pTopStack) % 8) pCppStack+=sizeof(sal_Int32); //align to 8 + break; + default: + break; + } +#endif + + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = + alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], + ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, + pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = + ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, + cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, + pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = + (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } + } + + + //===================================================================== + static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: [ret *], this, params + // _this_ ptr is patched cppu_XInterfaceProxy object + void *pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[1]; + } + else + { + pThis = pCallStack[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + sal_Int32 nMemberPos = + pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, + "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == + nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET(&pTD, + reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType()); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; + } +} + +//======================================================================= +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ + +extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, + void **pCallStack ) +{ + sal_Int64 nRegReturn; + typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, + &nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn); + break; + case typelib_TypeClass_VOID: + default: + break; + } + + return nRegReturn; +} + +extern "C" void privateSnippetExecutor(void); + +namespace +{ + const int codeSnippetSize = 20; + + unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex, + sal_Int32 vtableOffset, bool bHasHiddenParam) + { + if (bHasHiddenParam) + functionIndex |= 0x80000000; + + unsigned long * p = (unsigned long *)code; + + // ARM (not thumb) mode instructions + // mov ip, pc + *p++ = 0xE1A0C00F; + // ldr pc, [pc, #4] + *p++ = 0xE59FF004; + *p++ = (unsigned long)functionIndex; + *p++ = (unsigned long)vtableOffset; + *p++ = (unsigned long)privateSnippetExecutor; + + return code + codeSnippetSize; + } +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) + { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member ); + + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )); + + // Setter: + if (!pAttrTD->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, false); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + (s++)->fn = code + writetoexecdiff; + + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >(member); + + code = codeSnippet(code, functionOffset++, vtableOffset, + arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)); + break; + } + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *beg, unsigned char const *end) +{ + static void (*clear_cache)(unsigned char const*, unsigned char const*) + = (void (*)(unsigned char const*, unsigned char const*)) + dlsym(RTLD_DEFAULT, "__clear_cache"); + (*clear_cache)(beg, end); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx new file mode 100644 index 000000000000..d8452d8db027 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx @@ -0,0 +1,342 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + +extern sal_Int32 * pHack; +extern sal_Int32 nHack; + +namespace CPPU_CURRENT_NAMESPACE +{ + void dummy_can_throw_anything( char const * ) + { + } + + //=================================================================== + static OUString toUNOname( char const * p ) SAL_THROW( () ) + { +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif + } + + //===================================================================== + class RTTI + { + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + + public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI(typelib_CompoundTypeDescription *) SAL_THROW( () ); + }; + //____________________________________________________________________ + RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) + { + } + //____________________________________________________________________ + RTTI::~RTTI() SAL_THROW( () ) + { + dlclose( m_hApp ); + } + + //____________________________________________________________________ + type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) + { + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) ); + if (iFind2 == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind2->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; + } + + //------------------------------------------------------------------ + static void deleteException( void * pExc ) + { + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } + } + + //================================================================== + void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) + { +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + + __cxa_throw( pCppExc, rtti, deleteException ); + } + +#ifdef __ARM_EABI__ + static void* getAdjustedPtr(__cxa_exception* header) + { + return (void*)header->unwindHeader.barrier_cache.bitpattern[0]; + } +#else + static void* getAdjustedPtr(__cxa_exception* header) + { + return header->adjustedPtr; + } +#endif + + //=================================================================== + void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) + { + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk new file mode 100644 index 000000000000..2c42dec5a415 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCLINUXRgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/armhelper.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.S + $(CXX) -c -o $(SLO)$/$(@:b).o $< -fPIC ; touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx new file mode 100644 index 000000000000..2b00c6c008b4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _ARM_SHARE_HXX +#define _ARM_SHARE_HXX +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> +#include <unwind.h> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + // -- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + + struct __cxa_exception + { + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; +#ifdef __ARM_EABI__ + __cxa_exception *nextPropagatingException; + int propagationCount; +#else + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; +#endif + _Unwind_Exception unwindHeader; + }; + + extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); + extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, + void (*dest) (void *) ) __attribute__((noreturn)); + + struct __cxa_eh_globals + { + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +#ifdef __ARM_EABI__ + __cxa_exception *propagatingExceptions; +#endif + }; + extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + + // ----- + + //==================================================================== + void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + //==================================================================== + void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace arm +{ + enum armlimits { MAX_GPR_REGS = 4 }; + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx new file mode 100644 index 000000000000..5b02678b8fbf --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx @@ -0,0 +1,670 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <rtl/alloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include <bridges/cpp_uno/shared/bridge.hxx> +#include <bridges/cpp_uno/shared/types.hxx> +#include <bridges/cpp_uno/shared/unointerfaceproxy.hxx> +#include <bridges/cpp_uno/shared/vtables.hxx> + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + +/* + * Based on http://gcc.gnu.org/PR41443 + * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code + * should be used for *soft-float ABI* whether or not VFP is enabled, + * and __SOFTFP__ does specifically mean soft-float not soft-float ABI. + * + * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then + * -mfloat-abi=softfp should work. -mfloat-abi=hard won't; that would + * need both a new macro to identify the hard-VFP ABI. + */ +#if !defined(__ARM_EABI__) && !defined(__SOFTFP__) +#error Not Implemented + +/* + some possibly handy code to detect that we have VFP registers + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <elf.h> + +#define HWCAP_ARM_VFP 64 + +int hasVFP(void) +{ + int fd = open ("/proc/self/auxv", O_RDONLY); + if (fd == -1) + return -1; + + int ret = -1; + + Elf32_auxv_t buf[128]; + ssize_t n; + while ((ret == -1) && ((n = read(fd, buf, sizeof (buf))) > 0)) + { + for (int i = 0; i < 128; ++i) + { + if (buf[i].a_type == AT_HWCAP) + { + ret = (buf[i].a_un.a_val & HWCAP_ARM_VFP) ? true : false; + break; + } + else if (buf[i].a_type == AT_NULL) + { + ret = -2; + break; + } + } + } + + close (fd); + return ret; +} + +#endif + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace arm +{ + bool is_complex_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT || + p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = is_complex_struct(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return true; + } + if (p->pBaseTypeDescription != 0) + return is_complex_struct(&p->pBaseTypeDescription->aBase); + return false; + } + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return false; + else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + //A Composite Type not larger than 4 bytes is returned in r0 + bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return true; + } +} + +void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn) +{ +#if !defined(__ARM_EABI__) && !defined(__SOFTFP__) + register float fret asm("f0"); + register double dret asm("f0"); +#endif + + switch( pReturnType->eTypeClass ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pRegisterReturn[1] = r1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pRegisterReturn[0] = r0; + break; + case typelib_TypeClass_FLOAT: +#if defined(__ARM_EABI__) || defined(__SOFTFP__) + pRegisterReturn[0] = r0; +#else + *(float*)pRegisterReturn = fret; +#endif + break; + case typelib_TypeClass_DOUBLE: +#if defined(__ARM_EABI__) || defined(__SOFTFP__) + pRegisterReturn[1] = r1; + pRegisterReturn[0] = r0; +#else + *(double*)pRegisterReturn = dret; +#endif + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + if (!arm::return_in_hidden_param(pReturnType)) + pRegisterReturn[0] = r0; + break; + } + default: + break; + } +} + +namespace +{ +//================================================================ + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescriptionReference * pReturnType, + sal_uInt32 *pStack, + sal_uInt32 nStack, + sal_uInt32 *pGPR, + sal_uInt32 nGPR) __attribute__((noinline)); + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescriptionReference * pReturnType, + sal_uInt32 *pStack, + sal_uInt32 nStack, + sal_uInt32 *pGPR, + sal_uInt32 nGPR) +{ + // never called + if (! pThis) + CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + if ( nStack ) + { + // 8-bytes aligned + sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 8; + sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes ); + memcpy( stack, pStack, nStackBytes ); + } + + // Should not happen, but... + if ( nGPR > arm::MAX_GPR_REGS ) + nGPR = arm::MAX_GPR_REGS; + + sal_uInt32 pMethod = *((sal_uInt32*)pThis); + pMethod += 4 * nVtableIndex; + pMethod = *((sal_uInt32 *)pMethod); + + typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32); + FunctionCall pFunc = (FunctionCall)pMethod; + + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]); + + sal_uInt32 r0; + sal_uInt32 r1; + + // get return value + __asm__ __volatile__ ( + "mov %0, r0\n\t" + "mov %1, r1\n\t" + : "=r" (r0), "=r" (r1) : ); + + MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn); +} +} + +#define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#ifdef __ARM_EABI__ +#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \ + if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \ + { \ + ++nr; \ + } \ + if ( nr < arm::MAX_GPR_REGS ) \ + { \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \ + } \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + { \ + if ( (pDS - pStart) % 2) \ + { \ + ++pDS; \ + } \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \ + } +#else +#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \ + INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \ + INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow) +#endif + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \ + INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \ + INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) + +#define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +namespace { +//======================================================================= +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca( + sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + sal_uInt32 * pStackStart = pStack; + + sal_uInt32 pGPR[arm::MAX_GPR_REGS]; + sal_uInt32 nGPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + bool bOverFlow = false; + bool bSimpleReturn = true; + if (pReturnTypeDescr) + { + if (arm::return_in_hidden_param( pReturnTypeRef ) ) + bSimpleReturn = false; + + if (bSimpleReturn) + pCppReturn = pUnoReturn; // direct way for simple types + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? __builtin_alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + + INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack, bOverFlow ); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +// uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], + uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]); +#endif + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "long is %x\n", pCppArgs[nPos]); +#endif + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow ); + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeRef, + pStackStart, + (pStack - pStackStart), + pGPR, nGPR); + + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { +// __asm__ __volatile__ ("sub sp, sp, #2048\n"); + + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *> + (pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; + cpp_call( + pThis, aVtableSlot, // get, then set method + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceMethodTypeDescription const *> + (pMemberDescr))); + + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/call.cxx b/bridges/source/cpp_uno/gcc3_linux_hppa/call.cxx new file mode 100644 index 000000000000..f434b7e0ba91 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/call.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <rtl/alloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include <bridges/cpp_uno/shared/bridge.hxx> +#include <bridges/cpp_uno/shared/types.hxx> +#include <bridges/cpp_uno/shared/unointerfaceproxy.hxx> +#include <bridges/cpp_uno/shared/vtables.hxx> + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(sal_uInt32 ret0, sal_uInt32 ret1, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn, sal_uInt32 *pRegisterReturn) +{ + register float fret asm("fr4"); + register double dret asm("fr4"); + + switch (pReturnTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pRegisterReturn[1] = ret1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pRegisterReturn[0] = ret0; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = fret; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + if (bRegisterReturn) + { + pRegisterReturn[0] = ret0; + pRegisterReturn[1] = ret1; + } + break; + } + default: + break; + } +} + +//Moved callVirtual into this .cxx so that I can do this and get gcc to not +//touch r28 without having to learn any more pa-risc assembly than is +//strictly necessary +register sal_uInt32 r28 __asm__("%r28"); + +void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn, + sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, double *pFPR) __attribute__((noinline)); + +void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn, + sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, double *pFPR) +{ + register sal_uInt32* sp __asm__("%r30"); + + sal_uInt32 pMethod = *((sal_uInt32*)pThis); + pMethod += 4 * nVtableIndex; + pMethod = *((sal_uInt32 *)pMethod); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "this is %p\n", pGPR[0]); + for (int i = 0; i < hppa::MAX_GPR_REGS ; ++i) + fprintf(stderr, "normal reg %d is %d %x\n", i, pGPR[i], pGPR[i]); + + for (int i = 0; i < hppa::MAX_SSE_REGS ; ++i) + fprintf(stderr, "float reg %d is %x\n", i, pFPR[i]); + + for (int i = 0; i < nStack; ++i) + fprintf(stderr, "stack bytes are %x\n", pStack[i]); +#endif + + //Always reserve 4 slots, and align to 8 bytes + sal_uInt32 nStackBytes = ( ( nStack + 4 + 1 ) >> 1 ) * 8; + __builtin_alloca(nStackBytes); + sal_uInt32 *stack = sp-8; + int o = -5; + for (sal_uInt32 i = 0; i < nStack; ++i, --o) + stack[o] = pStack[i]; + + typedef int (* FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + asm volatile("fldd %0, %%fr4" : : "m"(pFPR[0]) : "fr4"); + asm volatile("fldd %0, %%fr5" : : "m"(pFPR[1]) : "fr5"); + asm volatile("fldd %0, %%fr6" : : "m"(pFPR[2]) : "fr6"); + asm volatile("fldd %0, %%fr7" : : "m"(pFPR[3]) : "fr7"); + asm volatile("ldw %0, %%r28" : : "m"(pRegisterReturn) : "r28"); + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]); + + register sal_uInt32 r29 __asm__("%r29"); + MapReturn(r28, r29, pReturnTypeDescr, bRegisterReturn, (sal_uInt32*)pRegisterReturn); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx new file mode 100644 index 000000000000..e96217495ddb --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx @@ -0,0 +1,726 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <boost/unordered_map.hpp> + +#include <rtl/alloc.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include <dlfcn.h> + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + + static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy* pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + long r8, void ** gpreg, double *fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + void ** startovrflw = ovrflw; + int nregs = 0; //number of words passed in registers + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "cpp2uno_call\n"); +#endif + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + // complex return ptr: if != 0 && != pUnoReturn, reconversion need + void * pCppReturn = 0; + + if (pReturnTypeDescr) + { + if (hppa::isRegisterReturn(pReturnTypeRef)) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple return\n"); +#endif + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex return via r8\n"); +#endif + pCppReturn = (void *)r8; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + fpreg++; + nregs++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion + // cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = + (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + bool bOverFlowUsed = false; + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_DOUBLE: + if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1)) + { + gpreg++; + fpreg++; + nregs++; + } + if (nregs < hppa::MAX_WORDS_IN_REGS-1) + { + fpreg++; + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; + gpreg+=2; + fpreg+=2; + nregs+=2; + } + else + { + if ((startovrflw-ovrflw) & 1) + ovrflw--; + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw-=2; + break; + case typelib_TypeClass_FLOAT: + if (nregs < hppa::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw--; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1)) + { + gpreg++; + fpreg++; + nregs++; + } + if (nregs < hppa::MAX_WORDS_IN_REGS-1) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg+=2; + fpreg+=2; + nregs+=2; + } + else + { + if ((startovrflw-ovrflw) & 1) + ovrflw--; + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw-=2; + break; + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (nregs < hppa::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg + 3); + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+3); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw--; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (nregs < hppa::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg+2); + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+2); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw--; + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + default: + if (nregs < hppa::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw--; + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + void *pCppStack; + + if (nregs < hppa::MAX_WORDS_IN_REGS) + { + pCppArgs[nPos] = pCppStack = *gpreg; + gpreg++; + fpreg++; + nregs++; + } + else + { + pCppArgs[nPos] = pCppStack = *ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw--; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "before dispatch\n"); +#endif + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "after dispatch\n"); +#endif + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], + ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, + pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = + ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, + cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, + pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = + (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } + } + + + //===================================================================== + static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + void ** gpreg, double* fpreg, + long sp, long r8, + sal_Int64 * pRegisterReturn /* space for register return */ ) + + { + void ** ovrflw = (void**)(sp); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "cpp_mediate with\n"); + fprintf(stderr, "%x %x\n", nFunctionIndex, nVtableOffset); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[0]), (long)(ovrflw[-1])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-2]), (long)(ovrflw[-3])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-4]), (long)(ovrflw[-5])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-6]), (long)(ovrflw[-7])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-8]), (long)(ovrflw[-9])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-10]), (long)(ovrflw[-11])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-12]), (long)(ovrflw[-13])); + fprintf(stderr, "and %x %x\n", (long)(ovrflw[-14]), (long)(ovrflw[-15])); +#endif + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + void * pThis; + if (nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[0]\n"); +#endif + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + sal_Int32 nMemberPos = + pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, + "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == + nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET(&pTD, + reinterpret_cast<Type *>(gpreg[1])->getTypeLibType()); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( r8 ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = (void*)r8; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; + } +} + +//======================================================================= +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ + +sal_Int64 cpp_vtable_call( sal_uInt32 in0, sal_uInt32 in1, sal_uInt32 in2, sal_uInt32 in3, sal_uInt32 firstonstack ) +{ + register sal_Int32 r21 asm("r21"); + register sal_Int32 r22 asm("r22"); + register sal_Int32 r28 asm("r28"); + sal_Int32 functionIndex = r21; + sal_Int32 vtableOffset = r22; + sal_Int32 r8 = r28; + + long sp = (long)&firstonstack; + + sal_uInt32 gpreg[hppa::MAX_GPR_REGS]; + gpreg[0] = in0; + gpreg[1] = in1; + gpreg[2] = in2; + gpreg[3] = in3; + + float fpreg[hppa::MAX_SSE_REGS]; //todo + register float f0 asm("fr4"); fpreg[0] = f0; + register float f1 asm("fr5"); fpreg[1] = f1; + register float f2 asm("fr6"); fpreg[2] = f2; + register float f3 asm("fr7"); fpreg[3] = f3; + + double dpreg[hppa::MAX_SSE_REGS]; //todo + register double d0 asm("fr4"); dpreg[0] = d0; + register double d1 asm("fr5"); dpreg[1] = d1; + register double d2 asm("fr6"); dpreg[2] = d2; + register double d3 asm("fr7"); dpreg[3] = d3; + + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "got to cpp_vtable_call with %x %x\n", functionIndex, vtableOffset); + for (int i = 0; i < hppa::MAX_GPR_REGS; ++i) + fprintf(stderr, "reg %d is %d %x\n", i, gpreg[i], gpreg[i]); + for (int i = 0; i < hppa::MAX_SSE_REGS; ++i) + fprintf(stderr, "float reg %d is %f %x\n", i, fpreg[i], ((long*)fpreg)[i]); + for (int i = 0; i < 4; ++i) + fprintf(stderr, "double reg %d is %f %llx\n", i, dpreg[i], ((long long*)dpreg)[i]); +#endif + + sal_Int64 nRegReturn; + + typelib_TypeClass aType = + cpp_mediate( functionIndex, vtableOffset, (void**)gpreg, dpreg, sp, r8, &nRegReturn); + + switch( aType ) + { + case typelib_TypeClass_FLOAT: + f0 = (*((float*)&nRegReturn)); + break; + case typelib_TypeClass_DOUBLE: + d0 = (*((double*)&nRegReturn)); + break; + default: + break; + } + + return nRegReturn; +} + + +namespace +{ + const int codeSnippetSize = 44; + +# define unldil(v) (((v & 0x7c) << 14) | ((v & 0x180) << 7) | ((v & 0x3) << 12) | ((v & 0xffe00) >> 8) | ((v & 0x100000) >> 20)) +# define L21(v) unldil(((unsigned long)(v) >> 11) & 0x1fffff) //Left 21 bits +# define R11(v) (((unsigned long)(v) & 0x7FF) << 1) //Right 11 bits + + unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex, + sal_Int32 vtableOffset, bool bHasHiddenParam) + { + if (bHasHiddenParam) + functionIndex |= 0x80000000; + + unsigned char * p = code; + *(unsigned long*)&p[0] = 0xeaa00000; // b,l 0x8,r21 + *(unsigned long*)&p[4] = 0xd6a01c1e; // depwi 0,31,2,r21 + *(unsigned long*)&p[8] = 0x4aa10040; // ldw 32(r21),r1 + + *(unsigned long*)&p[12] = 0x22A00000 | L21(functionIndex); // ldil L<functionIndex>,r21 + *(unsigned long*)&p[16] = 0x36B50000 | R11(functionIndex); // ldo R<functionIndex>,r21 + + *(unsigned long*)&p[20] = 0x22C00000 | L21(vtableOffset); // ldil L<vtableOffset>,r22 + *(unsigned long*)&p[24] = 0x36D60000 | R11(vtableOffset); // ldo R<vtableOffset>,r22 + + *(unsigned long*)&p[28] = 0x0c201094; // ldw 0(r1),r20 + *(unsigned long*)&p[32] = 0xea80c000; // bv r0(r20) + *(unsigned long*)&p[36] = 0x0c281093; // ldw 4(r1),r19 + *(unsigned long*)&p[40] = ((unsigned long)(cpp_vtable_call) & ~2); + + return code + codeSnippetSize; + } +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) + { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, false); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, false); + } + break; + case typelib_TypeClass_INTERFACE_METHOD: + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, false); + break; + } + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *beg, unsigned char const *end) +{ + void *p = (void*)((size_t)beg & ~31); + size_t stride = 32; + while (p < end) + { + asm volatile("fdc (%0)\n\t" + "sync\n\t" + "fic,m %1(%%sr4, %0)\n\t" + "sync" : "+r"(p) : "r"(stride) : "memory"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/except.cxx b/bridges/source/cpp_uno/gcc3_linux_hppa/except.cxx new file mode 100644 index 000000000000..1128f0f85cd8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/except.cxx @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + +extern sal_Int32 * pHack; +extern sal_Int32 nHack; + +namespace CPPU_CURRENT_NAMESPACE +{ + void dummy_can_throw_anything( char const * ) + { + } + + //=================================================================== + static OUString toUNOname( char const * p ) SAL_THROW( () ) + { +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif + } + + //===================================================================== + class RTTI + { + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + + public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI(typelib_CompoundTypeDescription *) SAL_THROW( () ); + }; + //____________________________________________________________________ + RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) + { + } + //____________________________________________________________________ + RTTI::~RTTI() SAL_THROW( () ) + { + dlclose( m_hApp ); + } + + //____________________________________________________________________ + type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) + { + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; + } + + //------------------------------------------------------------------ + static void deleteException( void * pExc ) + { + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } + } + + //================================================================== + void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) + { +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + + __cxa_throw( pCppExc, rtti, deleteException ); + } + + static void* getAdjustedPtr(__cxa_exception* header) + { + return header->adjustedPtr; + } + + //=================================================================== + void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) + { + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_hppa/makefile.mk new file mode 100644 index 000000000000..6fab7a4d1f5f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)" == "GCCLINUXH" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/share.hxx b/bridges/source/cpp_uno/gcc3_linux_hppa/share.hxx new file mode 100644 index 000000000000..895acf6b1883 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/share.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + + +namespace hppa +{ + enum hppalimits { MAX_WORDS_IN_REGS = 4, MAX_GPR_REGS = 4, MAX_SSE_REGS = 4 }; + + bool isRegisterReturn( typelib_TypeDescriptionReference *pTypeRef ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx new file mode 100644 index 000000000000..6c3b25c387fa --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx @@ -0,0 +1,522 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <rtl/alloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include <bridges/cpp_uno/shared/bridge.hxx> +#include <bridges/cpp_uno/shared/types.hxx> +#include <bridges/cpp_uno/shared/unointerfaceproxy.hxx> +#include <bridges/cpp_uno/shared/vtables.hxx> + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn, + sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, double *pFPR); + +#define INSERT_INT32( pSV, nr, pGPR, pDS, bOverFlow )\ + if (nr < hppa::MAX_WORDS_IN_REGS) \ + { \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + } \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverFlow )\ + if ( (nr < hppa::MAX_WORDS_IN_REGS) && (nr % 2) ) \ + { \ + ++nr; \ + } \ + if ( nr < hppa::MAX_WORDS_IN_REGS ) \ + { \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \ + } \ + else \ + bOverFlow = true; \ + if ( bOverFlow ) \ + { \ + if ( (pDS - pStart) % 2) \ + ++pDS; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \ + } + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverFlow ) \ + if (nr < hppa::MAX_WORDS_IN_REGS) \ + { \ + sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr++]); \ + pDouble[0] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + } \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverFlow ) \ + if ( (nr < hppa::MAX_WORDS_IN_REGS) && (nr % 2) ) \ + { \ + ++nr; \ + } \ + if ( nr < hppa::MAX_WORDS_IN_REGS ) \ + { \ + sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr+1]); \ + pDouble[0] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + pDouble[1] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \ + nr+=2; \ + } \ + else \ + bOverFlow = true; \ + if ( bOverFlow ) \ + { \ + if ( (pDS - pStart) % 2) \ + ++pDS; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \ + *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \ + } + +#define INSERT_INT16( pSV, nr, pGPR, pDS, bOverFlow ) \ + if ( nr < hppa::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS, bOverFlow ) \ + if ( nr < hppa::MAX_WORDS_IN_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +namespace hppa +{ + bool is_complex_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT || + p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = is_complex_struct(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return true; + } + if (p->pBaseTypeDescription != 0) + return is_complex_struct(&p->pBaseTypeDescription->aBase); + return false; + } + + bool isRegisterReturn( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return true; + else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + /* If the struct is larger than 8 bytes, then there is a buffer at r8 to stick the return value into */ + bool bRet = pTypeDescr->nSize <= 8 && !is_complex_struct(pTypeDescr); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return false; + } +} + + +namespace { +//======================================================================= +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca( + sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + sal_uInt32 * pStackStart = pStack; + + sal_uInt32 pGPR[hppa::MAX_GPR_REGS]; + double pFPR[hppa::MAX_SSE_REGS]; + sal_uInt32 nRegs=0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + bool bOverFlow = false; + bool bRegisterReturn = true; + + if (pReturnTypeDescr) + { + + bRegisterReturn = hppa::isRegisterReturn(pReturnTypeRef); + if (bRegisterReturn) + pCppReturn = pUnoReturn; // direct way for simple types + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? __builtin_alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + INSERT_INT32( &pAdjustedThisPtr, nRegs, pGPR, pStack, bOverFlow ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "hyper is %llx\n", *((long long*)pCppArgs[nPos])); +#endif + INSERT_INT64( pCppArgs[nPos], nRegs, pGPR, pStack, pStackStart, bOverFlow ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "long is %x\n", pCppArgs[nPos]); +#endif + INSERT_INT32( pCppArgs[nPos], nRegs, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nRegs, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nRegs, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], nRegs, pFPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], nRegs, pFPR, pStack, pStackStart, bOverFlow ); + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT32( &(pCppArgs[nPos]), nRegs, pGPR, pStack, bOverFlow ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, bRegisterReturn, + pStackStart, + (pStack - pStackStart), pGPR, pFPR); + + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *> + (pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; + cpp_call( + pThis, aVtableSlot, // get, then set method + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceMethodTypeDescription const *> + (pMemberDescr))); + + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/call.s b/bridges/source/cpp_uno/gcc3_linux_ia64/call.s new file mode 100644 index 000000000000..8073127da3e3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/call.s @@ -0,0 +1,20 @@ +/* ia64 support code for OpenOffice C++/UNO bridging + * + * Caolan McNamara <caolanm@redhat.com> + */ + .text + .align 16 + .global privateSnippetExecutor# + .proc privateSnippetExecutor# +privateSnippetExecutor: + adds r15 = 8, gp /* r15 now points to real gp value*/ + ;; + ld8 r14 = [gp] /* load nOffsetAndIndex into a handy register */ + ld8 gp = [r15] /* load real gp value into gp */ + ;; + /* store the address where large structs are "returned" into a handy register */ + mov r15 = r8 + ;; + br cpp_vtable_call# /* call cpp_vtable_call which'll suck out r14 */ + ;; + .endp privateSnippetExecutor# diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx new file mode 100644 index 000000000000..e897397ce76b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx @@ -0,0 +1,685 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include <stdio.h> + +extern "C" { extern void (*privateSnippetExecutor)(); } + +using namespace ::com::sun::star::uno; + +namespace +{ +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, long r8, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "as far as cpp2uno_call\n"); +#endif + + int ng = 0; //number of gpr registers used + int nf = 0; //number of fpr regsiters used + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if ( ia64::return_in_hidden_param( pReturnTypeRef ) ) // complex return via ptr passed as hidden parameter reg (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + ng++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + else if ( ia64::return_via_r8_buffer( pReturnTypeRef ) ) // complex return via ptr passed in r8 + { + pCppReturn = (void *)r8; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + + else + pUnoReturn = pRegisterReturn; // direct way for simple types + } + // pop this + gpreg++; + ng++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + bool bOverFlowUsed = false; + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + //I think it is impossible to get UNO to pass structs as parameters by copy + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple\n"); +#endif + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_FLOAT: + if (nf < ia64::MAX_SSE_REGS && ng < ia64::MAX_GPR_REGS) + { + float tmp = (float) (*((double *)fpreg)); + (*((float *) fpreg)) = tmp; + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++; + nf++; + gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + case typelib_TypeClass_DOUBLE: + if (nf < ia64::MAX_SSE_REGS && ng < ia64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++; + nf++; + gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + default: + if (ng < ia64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex, ng is %d\n", ng); +#endif + void *pCppStack; //temporary stack pointer + + if (ng < ia64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pCppStack = *gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pCppStack = *ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of params\n"); +#endif + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = ia64::return_via_r8_buffer(pReturnTypeRef) ? typelib_TypeClass_VOID : (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_uInt64 nOffsetAndIndex, + void ** gpreg, void ** fpreg, long sp, long r8, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" ); + + sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32); + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); + + void ** ovrflw = (void**)(sp); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + void * pThis; + if (nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[0]\n"); +#endif + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is %p\n", pThis); +#endif + + pThis = static_cast< char * >(pThis) - nVtableOffset; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is now %p\n", pThis); +#endif + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "indexes are %d %d\n", nFunctionIndex, pTypeDescr->nMapFunctionIndexToMemberIndex); +#endif + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "members are %d %d\n", nMemberPos, pTypeDescr->nAllMembers); +#endif + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + r8, gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "screwed\n"); +#endif + + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of cpp_mediate\n"); +#endif + return eRet; +} +} + +extern "C" ia64::RegReturn cpp_vtable_call( + long in0, long in1, long in2, long in3, long in4, long in5, long in6, long in7, + long firstonstack + ) +{ + register long r15 asm("r15"); + long r8 = r15; + + register long r14 asm("r14"); + long nOffsetAndIndex = r14; + + long sp = (long)&firstonstack; + + sal_uInt64 gpreg[ia64::MAX_GPR_REGS]; + gpreg[0] = in0; + gpreg[1] = in1; + gpreg[2] = in2; + gpreg[3] = in3; + gpreg[4] = in4; + gpreg[5] = in5; + gpreg[6] = in6; + gpreg[7] = in7; + + double fpreg[ia64::MAX_SSE_REGS]; + register double f8 asm("f8"); fpreg[0] = f8; + register double f9 asm("f9"); fpreg[1] = f9; + register double f10 asm("f10"); fpreg[2] = f10; + register double f11 asm("f11"); fpreg[3] = f11; + register double f12 asm("f12"); fpreg[4] = f12; + register double f13 asm("f13"); fpreg[5] = f13; + register double f14 asm("f14"); fpreg[6] = f14; + register double f15 asm("f15"); fpreg[7] = f15; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "cpp_vtable_call called with %lx\n", nOffsetAndIndex); + fprintf(stderr, "adump is %lx %lx %lx %lx %lx %lx %lx %lx\n", in0, in1, in2, in3, in4, in5, in6, in7); + fprintf(stderr, "bdump is %f %f %f %f %f %f %f %f\n", f8, f9, f10, f11, f12, f13, f14, f15); +#endif + + volatile long nRegReturn[4] = { 0 }; + + typelib_TypeClass aType = + cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, sp, r8, (sal_Int64*)&nRegReturn[0]); + + ia64::RegReturn ret; + switch( aType ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_HYPER: + ret.r8 = nRegReturn[0]; + break; + case typelib_TypeClass_FLOAT: + asm volatile("ldfs f8=%0" : : "m"((*((float*)&nRegReturn))) : "f8"); + break; + case typelib_TypeClass_DOUBLE: + asm volatile("ldfd f8=%0" : : "m"((*((double*)&nRegReturn))) : "f8"); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + ret.r8 = nRegReturn[0]; + ret.r9 = nRegReturn[1]; + ret.r10 = nRegReturn[2]; + ret.r11 = nRegReturn[3]; + break; + } + default: + break; + } + return ret; +} + +namespace +{ +const int codeSnippetSize = 40; + +bridges::cpp_uno::shared::VtableFactory::Slot codeSnippet( unsigned char * code, sal_PtrDiff writetoexecdiff, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + bool bHasHiddenParam ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "size is %d\n", codeSnippetSize); + fprintf(stderr,"in codeSnippet functionIndex is %x\n", nFunctionIndex); + fprintf(stderr,"in codeSnippet vtableOffset is %x\n", nVtableOffset); +#endif + + sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex ); + + if ( bHasHiddenParam ) + nOffsetAndIndex |= 0x80000000; + + long *raw = (long *)code; + + bridges::cpp_uno::shared::VtableFactory::Slot* destination = (bridges::cpp_uno::shared::VtableFactory::Slot*)cpp_vtable_call; + + raw[0] = (long)&privateSnippetExecutor; + raw[1] = (long)&raw[2]; + raw[2] = nOffsetAndIndex; + raw[3] = destination->gp_value; + + return *(bridges::cpp_uno::shared::VtableFactory::Slot*)(code+writetoexecdiff); +} +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, unsigned char const *) +{ +} + +bridges::cpp_uno::shared::VtableFactory::Slot * bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot* bridges::cpp_uno::shared::VtableFactory::initializeBlock(void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + Slot foo = {0,0}; + slots[-2] = foo; + slots[-1] = foo; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** in_slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*in_slots) -= functionCount; + Slot * slots = *in_slots; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + *slots++ = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + ia64::return_in_hidden_param( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + code += codeSnippetSize; + + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + *slots++ = codeSnippet(code, writetoexecdiff, functionOffset++, vtableOffset, false); + code += codeSnippetSize; + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + *slots++ = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + ia64::return_in_hidden_param( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + code += codeSnippetSize; + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/except.cxx b/bridges/source/cpp_uno/gcc3_linux_ia64/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_ia64/makefile.mk new file mode 100644 index 000000000000..1e82cfabe260 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCLINUXAgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map + +SHL1OBJS= $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(CC) -c -o $(SLO)$/$(@:b).o $< -fpic ; touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_ia64/share.hxx new file mode 100644 index 000000000000..359c9c720212 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/share.hxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace ia64 +{ + enum ia64limits { MAX_GPR_REGS = 8, MAX_SSE_REGS = 8, MAX_REG_SLOTS = 8 }; + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); + bool return_via_r8_buffer( typelib_TypeDescriptionReference *pTypeRef ); + + struct RegReturn + { + long r8; + long r9; + long r10; + long r11; + }; +} + +namespace bridges +{ + namespace cpp_uno + { + namespace shared + { + /* + http://www.swag.uwaterloo.ca/asx/ABI.html + On Itanium, function pointers are pairs: the function address followed + by the global pointer value that should be used when calling the + function (code address, gp value) + */ + struct VtableFactory::Slot + { + sal_uInt64 code_address; + sal_uInt64 gp_value; + }; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_ia64/uno2cpp.cxx new file mode 100644 index 000000000000..19b586b557f2 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/uno2cpp.cxx @@ -0,0 +1,692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(const ia64::RegReturn &rRet, double dret, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, sal_uInt64 *pRegisterReturn) +{ + switch (pReturnTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pRegisterReturn = rRet.r8; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *pRegisterReturn = (unsigned short)rRet.r8; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *pRegisterReturn = (unsigned char)rRet.r8; + break; + case typelib_TypeClass_FLOAT: + *reinterpret_cast<float *>( pRegisterReturn ) = dret; + break; + case typelib_TypeClass_DOUBLE: + *reinterpret_cast<double *>( pRegisterReturn ) = dret; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + sal_uInt32 nRetSize = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 32 && nRetSize > 0) + memcpy(pRegisterReturn, (void*)&rRet, nRetSize); + break; + } + default: + break; + } +} + +namespace ia64 +{ + bool is_complex_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT || + p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = is_complex_struct(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return true; + } + if (p->pBaseTypeDescription != 0) + return is_complex_struct(&p->pBaseTypeDescription->aBase); + return false; + } + + bool is_complex_struct( typelib_TypeDescriptionReference *pTypeRef ) + { + if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + bool bRet = is_complex_struct( pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + + return bRet; + } + return false; + } + + bool return_via_r8_buffer( typelib_TypeDescriptionReference *pTypeRef ) + { + if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + if (is_complex_struct( pTypeRef )) return false; + + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + /* If the struct is larger than 32 bytes, then there is a buffer at r8 to stick the return value into */ + bool bRet = pTypeDescr->nSize > 32; + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return false; + } + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return false; + else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + return is_complex_struct( pTypeRef ); + return true; + } + + +} + +namespace +{ +//================================================================================================== +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ + // Stack, if used, must be 16-bytes aligned + if ( nStack ) + nStack = ( nStack + 1 ) & ~1; + + // Should not happen, but... + if ( nFPR > ia64::MAX_SSE_REGS ) + nFPR = ia64::MAX_SSE_REGS; + if ( nGPR > ia64::MAX_GPR_REGS ) + nGPR = ia64::MAX_GPR_REGS; + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( unsigned int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( unsigned int i = 0; i < nFPR; ++i ) + fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn); + } +#endif + + // Load parameters to stack, if necessary + sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 ); + memcpy( stack, pStack, nStack * 8 ); + + // To get pointer to method + // a) get the address of the vtable + sal_uInt64 pMethod = *((sal_uInt64 *)pThis); + // b) get the address from the vtable entry at offset, each entry is 16bytes, + // 8 for function pointer, and 8 for global pointer + pMethod += 16 * nVtableIndex; + + typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + switch (nFPR) //deliberate fall through + { + case 8: + asm volatile("ldfd f15=%0" : : "m"(pFPR[7]) : "f15"); + case 7: + asm volatile("ldfd f14=%0" : : "m"(pFPR[6]) : "f14"); + case 6: + asm volatile("ldfd f13=%0" : : "m"(pFPR[5]) : "f13"); + case 5: + asm volatile("ldfd f12=%0" : : "m"(pFPR[4]) : "f12"); + case 4: + asm volatile("ldfd f11=%0" : : "m"(pFPR[3]) : "f11"); + case 3: + asm volatile("ldfd f10=%0" : : "m"(pFPR[2]) : "f10"); + case 2: + asm volatile("ldfd f9=%0" : : "m"(pFPR[1]) : "f9"); + case 1: + asm volatile("ldfd f8=%0" : : "m"(pFPR[0]) : "f8"); + default: + break; + } + + //stick the return area into r8 for big struct returning + asm volatile("ld8 r8=%0" : : "m"(pRegisterReturn) : "r8"); + + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5], pGPR[6], pGPR[7]); + + register double f8 asm("f8"); + ia64::RegReturn ret; + { + register long r8 asm("r8"); ret.r8 = r8; + register long r9 asm("r9"); ret.r9 = r9; + register long r10 asm("r10"); ret.r10 = r10; + register long r11 asm("r11"); ret.r11 = r11; + } + + MapReturn(ret, f8, pReturnTypeDescr, bSimpleReturn, (sal_uInt64*)pRegisterReturn); +} + +// Macros for easier insertion of values to registers or stack +// pSV - pointer to the source +// nr - order of the value [will be increased if stored to register] +// pFPR, pGPR - pointer to the registers +// pDS - pointer to the stack [will be increased if stored here] + +// The value in %xmm register is already prepared to be retrieved as a float, +// thus we treat float and double the same +#define INSERT_FLOAT( pSV, nfr, pFPR, ngr, pGPR, pDS, bOverflow ) \ + if ( nfr < ia64::MAX_SSE_REGS && ngr < ia64::MAX_GPR_REGS ) \ + pFPR[nfr++] = *reinterpret_cast<float *>( pSV ); \ + if ( ngr < ia64::MAX_GPR_REGS ) \ + pGPR[ngr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_DOUBLE( pSV, nfr, pFPR, ngr, pGPR, pDS, bOverflow ) \ + if ( nfr < ia64::MAX_SSE_REGS && ngr < ia64::MAX_GPR_REGS ) \ + pFPR[nfr++] = *reinterpret_cast<double *>( pSV ); \ + if ( ngr < ia64::MAX_GPR_REGS ) \ + pGPR[ngr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_INT64( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ia64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ia64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ia64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ia64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; + + sal_uInt64 pGPR[ia64::MAX_GPR_REGS]; + sal_uInt32 nGPR = 0; + + double pFPR[ia64::MAX_SSE_REGS]; + sal_uInt32 nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + bool bOverFlow = false; + + bool bSimpleReturn = true; + if (pReturnTypeDescr) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass); +#endif + if ( ia64::return_in_hidden_param(pReturnTypeRef) || ia64::return_via_r8_buffer(pReturnTypeRef) ) + bSimpleReturn = false; + + if ( bSimpleReturn ) + { + pCppReturn = pUnoReturn; // direct way for simple types +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple return\n"); +#endif + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pCppReturn/pUnoReturn is %lx/%lx", pCppReturn, pUnoReturn); +#endif + if (!ia64::return_via_r8_buffer(pReturnTypeRef)) + INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack, bOverFlow ); + } + } + // push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "this pointer is %p\n", pAdjustedThisPtr); +#endif + INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow ); + + // Args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "n params is %d\n", nParams); +#endif + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "param %d is %d %d %d\n", nPos, rParam.bOut, bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ), + pParamTypeDescr->eTypeClass); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +// uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "hyper is %lx\n", *(unsigned long*)(pCppArgs[nPos])); +#endif + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "long is %lx\n", *(unsigned int*)(pCppArgs[nPos])); +#endif + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "short is %x\n", *(unsigned short*)(pCppArgs[nPos])); +#endif + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "byte is %x\n", *(unsigned char*)(pCppArgs[nPos])); +#endif + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_FLOAT: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "a float is %f\n", *(float*)(pCppArgs[nPos])); + fprintf(stderr, "b float is %f\n", *(double*)(pCppArgs[nPos])); +#endif + INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_DOUBLE: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "double is %f\n", *(double*)(pCppArgs[nPos])); +#endif + INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, nGPR, pGPR, pStack, bOverFlow ); + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex type again %d\n", rParam.bIn); +#endif + if (! rParam.bIn) // is pure out + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex size is %d\n", pParamTypeDescr->nSize ); +#endif + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "this one\n"); +#endif + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "that one, passing %lx through\n", pUnoArgs[nPos]); +#endif + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, bSimpleReturn, + pStackStart, ( pStack - pStackStart ), + pGPR, nGPR, + pFPR, nFPR ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/call.s b/bridges/source/cpp_uno/gcc3_linux_intel/call.s new file mode 100644 index 000000000000..45d7c5308d30 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/call.s @@ -0,0 +1,274 @@ + .text + +.globl privateSnippetExecutorGeneral + .type privateSnippetExecutorGeneral,@function +privateSnippetExecutorGeneral: +.LFBg: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIg0: + movl %esp,%ebp +.LCFIg1: + subl $0x8,%esp # 32bit returnValue, and preserve potential 128bit + # stack alignment + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + movl 16(%esp),%eax # 32bit returnValue + leave + ret +.LFEg: + .size privateSnippetExecutorGeneral,.-privateSnippetExecutorGeneral + +.globl privateSnippetExecutorVoid + .type privateSnippetExecutorVoid,@function +privateSnippetExecutorVoid: +.LFBv: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIv0: + movl %esp,%ebp +.LCFIv1: + andl $0xFFFFFFF0,%esp # preserve potential 128bit stack alignment + pushl $0 # 32bit null pointer (returnValue not used) + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + leave + ret +.LFEv: + .size privateSnippetExecutorVoid,.-privateSnippetExecutorVoid + +.globl privateSnippetExecutorHyper + .type privateSnippetExecutorHyper,@function +privateSnippetExecutorHyper: +.LFBh: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIh0: + movl %esp,%ebp +.LCFIh1: + subl $0x8,%esp # 64bit returnValue (preserves potential 128bit + # stack alignment) + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + movl 16(%esp),%eax # 64bit returnValue, lower half + movl 20(%esp),%edx # 64bit returnValue, upper half + leave + ret +.LFEh: + .size privateSnippetExecutorHyper,.-privateSnippetExecutorHyper + +.globl privateSnippetExecutorFloat + .type privateSnippetExecutorFloat,@function +privateSnippetExecutorFloat: +.LFBf: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIf0: + movl %esp,%ebp +.LCFIf1: + subl $0x8,%esp # 32bit returnValue, and preserve potential 128bit + # stack alignment + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + flds 16(%esp) # 32bit returnValue + leave + ret +.LFEf: + .size privateSnippetExecutorFloat,.-privateSnippetExecutorFloat + +.globl privateSnippetExecutorDouble + .type privateSnippetExecutorDouble,@function +privateSnippetExecutorDouble: +.LFBd: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFId0: + movl %esp,%ebp +.LCFId1: + subl $0x8,%esp # 64bit returnValue (preserves potential 128bit + # stack alignment) + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + fldl 16(%esp) # 64bit returnValue + leave + ret +.LFEd: + .size privateSnippetExecutorDouble,.-privateSnippetExecutorDouble + +.globl privateSnippetExecutorClass + .type privateSnippetExecutorClass,@function +privateSnippetExecutorClass: +.LFBc: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIc0: + movl %esp,%ebp +.LCFIc1: + subl $0x8,%esp # 32bit returnValue, and preserve potential 128bit + # stack alignment + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call cpp_vtable_call + movl 16(%esp),%eax # 32bit returnValue + leave + ret $4 +.LFEc: + .size privateSnippetExecutorClass,.-privateSnippetExecutorClass + + .section .eh_frame,"a",@progbits +.Lframe1: + .long .LECIE1-.LSCIE1 # length +.LSCIE1: + .long 0 # CIE_ID + .byte 1 # version + .string "zR" # augmentation + .uleb128 1 # code_alignment_factor + .sleb128 -4 # data_alignment_factor + .byte 8 # return_address_register + .uleb128 1 # augmentation size 1: + .byte 0x1B # FDE Encoding (pcrel sdata4) + # initial_instructions: + .byte 0x0C # DW_CFA_def_cfa %esp, 4 + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset ret, 1 + .uleb128 1 + .align 4 +.LECIE1: +.LSFDEg: + .long .LEFDEg-.LASFDEg # length +.LASFDEg: + .long .LASFDEg-.Lframe1 # CIE_pointer + .long .LFBg-. # initial_location + .long .LFEg-.LFBg # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIg0-.LFBg + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIg1-.LCFIg0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEg: +.LSFDEv: + .long .LEFDEv-.LASFDEv # length +.LASFDEv: + .long .LASFDEv-.Lframe1 # CIE_pointer + .long .LFBv-. # initial_location + .long .LFEv-.LFBv # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIv0-.LFBv + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIv1-.LCFIv0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEv: +.LSFDEh: + .long .LEFDEh-.LASFDEh # length +.LASFDEh: + .long .LASFDEh-.Lframe1 # CIE_pointer + .long .LFBh-. # initial_location + .long .LFEh-.LFBh # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIh0-.LFBh + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIh1-.LCFIh0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEh: +.LSFDEf: + .long .LEFDEf-.LASFDEf # length +.LASFDEf: + .long .LASFDEf-.Lframe1 # CIE_pointer + .long .LFBf-. # initial_location + .long .LFEf-.LFBf # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIf0-.LFBf + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIf1-.LCFIf0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEf: +.LSFDEd: + .long .LEFDEd-.LASFDEd # length +.LASFDEd: + .long .LASFDEd-.Lframe1 # CIE_pointer + .long .LFBd-. # initial_location + .long .LFEd-.LFBd # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFId0-.LFBd + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFId1-.LCFId0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEd: +.LSFDEc: + .long .LEFDEc-.LASFDEc # length +.LASFDEc: + .long .LASFDEc-.Lframe1 # CIE_pointer + .long .LFBc-. # initial_location + .long .LFEc-.LFBc # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIc0-.LFBc + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIc1-.LCFIc0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEc: + .section .note.GNU-stack,"",@progbits diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx new file mode 100644 index 000000000000..3f91c558f1d0 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx @@ -0,0 +1,529 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +void cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + void * pReturnValue ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (x86::isSimpleReturnType( pReturnTypeDescr )) + { + pUnoReturn = pReturnValue; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *static_cast< void ** >(pReturnValue) = pCppReturn; + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } +} + + +//================================================================================================== +extern "C" void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack, + void * pReturnValue ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pReturnValue ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pReturnValue ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *static_cast< void ** >(pReturnValue) = pCallStack[1]; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pReturnValue ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + } + } +} + +//================================================================================================== +extern "C" void privateSnippetExecutorGeneral(); +extern "C" void privateSnippetExecutorVoid(); +extern "C" void privateSnippetExecutorHyper(); +extern "C" void privateSnippetExecutorFloat(); +extern "C" void privateSnippetExecutorDouble(); +extern "C" void privateSnippetExecutorClass(); +extern "C" typedef void (*PrivateSnippetExecutor)(); + +int const codeSnippetSize = 16; + +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) || \ + defined(DRAGONFLY) +namespace +{ + PrivateSnippetExecutor returnsInRegister(typelib_TypeDescriptionReference * pReturnTypeRef) + { + //These archs apparently are returning small structs in registers, while Linux + //doesn't + PrivateSnippetExecutor exec=NULL; + + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + const bool bSimpleReturnStruct = x86::isSimpleReturnType(pReturnTypeDescr); + const sal_Int32 nRetSize = pReturnTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + if (bSimpleReturnStruct) + { + exec = privateSnippetExecutorGeneral; // fills eax + if (nRetSize > 4) + exec = privateSnippetExecutorHyper; // fills eax/edx + } + return exec; + } +} +#endif + +unsigned char * codeSnippet( + unsigned char * code, sal_PtrDiff writetoexecdiff, sal_Int32 functionIndex, sal_Int32 vtableOffset, + typelib_TypeDescriptionReference * pReturnTypeRef) +{ + PrivateSnippetExecutor exec; + typelib_TypeClass eReturnClass = pReturnTypeRef ? pReturnTypeRef->eTypeClass : typelib_TypeClass_VOID; + switch (eReturnClass) + { + case typelib_TypeClass_VOID: + exec = privateSnippetExecutorVoid; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + exec = privateSnippetExecutorHyper; + break; + case typelib_TypeClass_FLOAT: + exec = privateSnippetExecutorFloat; + break; + case typelib_TypeClass_DOUBLE: + exec = privateSnippetExecutorDouble; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: +#if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) || \ + defined(DRAGONFLY) + exec = returnsInRegister(pReturnTypeRef); + if (!exec) + { + exec = privateSnippetExecutorClass; + functionIndex |= 0x80000000; + } + break; +#endif + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + exec = privateSnippetExecutorClass; + functionIndex |= 0x80000000; + break; + default: + exec = privateSnippetExecutorGeneral; + break; + } + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov function_index, %eax: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov vtable_offset, %edx: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // jmp privateSnippetExecutor: + *p++ = 0xE9; + *reinterpret_cast< sal_Int32 * >(p) + = ((unsigned char *) exec) - p - sizeof (sal_Int32) - writetoexecdiff; + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + NULL); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/except.cxx b/bridges/source/cpp_uno/gcc3_linux_intel/except.cxx new file mode 100644 index 000000000000..02ac42b1d4e7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/except.cxx @@ -0,0 +1,340 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <boost/unordered_map.hpp> + +#include <cxxabi.h> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) +#if defined(FREEBSD) && __FreeBSD_version < 702104 + : m_hApp( dlopen( 0, RTLD_NOW | RTLD_GLOBAL ) ) +#else + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +#endif +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); +#if defined(FREEBSD) && __FreeBSD_version < 702104 /* #i22253# */ + rtti = (type_info *)dlsym( RTLD_DEFAULT, symName.getStr() ); +#else + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); +#endif + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_intel/makefile.mk new file mode 100644 index 000000000000..26690d72fa7c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCLINUXIgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCOPENBSDIgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCFREEBSDIgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCNETBSDIgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCDRAGONFLYIgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +# In case the compiler supports AVX this code segfaults so specifically turn +# it off. +.IF "$(HAVE_GCC_AVX)" == "TRUE" + CFLAGSCXX+= -mno-avx +.ENDIF + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(CC) -c -o $(SLO)$/$(@:b).o $< + touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx b/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx new file mode 100644 index 000000000000..8a3e136bfb7b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); + +} + +namespace x86 +{ + bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx new file mode 100644 index 000000000000..21febefad110 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY) +#include <stdlib.h> +#else +#include <malloc.h> +#endif + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + // preserve potential 128bit stack alignment + "and $0xfffffff0, %%esp\n\t" + "mov %0, %%eax\n\t" + "lea -4(,%%eax,4), %%eax\n\t" + "and $0xf, %%eax\n\t" + "sub $0xc, %%eax\n\t" + "add %%eax, %%esp\n\t" + // copy values + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + switch( pReturnTypeDescr->eTypeClass ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + default: + { +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) || \ + defined(DRAGONFLY) + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 8 && nRetSize > 0) + { + if (nRetSize > 4) + static_cast<long *>(pRegisterReturn)[1] = edx; + static_cast<long *>(pRegisterReturn)[0] = eax; + } +#else + (void)bSimpleReturn; +#endif + break; + } + } +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + bool bSimpleReturn = true; + + if (pReturnTypeDescr) + { + bSimpleReturn = x86::isSimpleReturnType(pReturnTypeDescr); + if (bSimpleReturn) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, bSimpleReturn, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace x86 +{ + bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive) + { + if (bridges::cpp_uno::shared::isSimpleType( pTD )) + return true; +#if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || \ + defined(MACOSX) || defined(DRAGONFLY) + // Only structs of exactly 1, 2, 4, or 8 bytes are returned through + // registers, see <http://developer.apple.com/documentation/DeveloperTools/ + // Conceptual/LowLevelABI/Articles/IA32.html>: + if (pTD->eTypeClass == typelib_TypeClass_STRUCT && + (recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8)) + { + typelib_CompoundTypeDescription *const pCompTD = + (typelib_CompoundTypeDescription *) pTD; + for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) { + typelib_TypeDescription * pMemberTD = 0; + TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] ); + bool const b = isSimpleReturnType(pMemberTD, true); + TYPELIB_DANGER_RELEASE( pMemberTD ); + if (! b) + return false; + } + return true; + } +#else + (void)recursive; +#endif + return false; + } +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx new file mode 100644 index 000000000000..7c46d1a0b408 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx @@ -0,0 +1,534 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <boost/unordered_map.hpp> + +#include <rtl/alloc.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include <dlfcn.h> + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + + static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy* pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + long r8, void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + // pCallStack: ret, [return ptr], this, params + char * pTopStack = (char *)(pCallStack + 0); + char * pCppStack = pTopStack; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "cpp2uno_call\n"); +#endif + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + // complex return ptr: if != 0 && != pUnoReturn, reconversion need + void * pCppReturn = 0; + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple return\n"); +#endif + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex return\n"); +#endif + pCppReturn = (void *)r8; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), + "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion + // cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = + (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && + bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + pCppArgs[nPos] = pCppStack + 3; + pUnoArgs[nPos] = pCppStack + 3; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pCppArgs[nPos] = pCppStack + 2; + pUnoArgs[nPos] = pCppStack + 2; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "before dispatch\n"); +#endif + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "after dispatch\n"); +#endif + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], + ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, + pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = + ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, + cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, + pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = + (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } + } + + + //===================================================================== + static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + long sp, long r8, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + void ** pCallStack = (void**)(sp); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "cpp_mediate with\n"); + fprintf(stderr, "%x %x\n", nFunctionIndex, nVtableOffset); + fprintf(stderr, "and %x %x\n", pCallStack, pRegisterReturn); + fprintf(stderr, "and %x %x\n", pCallStack[0], pCallStack[1]); +#endif + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + void *pThis = pCallStack[0]; + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + sal_Int32 nMemberPos = + pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, + "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == + nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + r8, pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + r8, pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET(&pTD, + reinterpret_cast<Type *>(pCallStack[1])->getTypeLibType()); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( r8 ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = (void*)r8; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + r8, pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; + } +} + +//======================================================================= +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ + +extern "C" sal_Int64 cpp_vtable_call( long firstonstack ) +{ + register long d0 asm("d0"); + long functionIndex = d0; + + register long a1 asm("a1"); + long r8 = a1; + + register long d1 asm("d1"); + long vtableOffset = d1; + + long sp = (long)&firstonstack; + + sal_Int64 nRegReturn; + cpp_mediate( functionIndex, vtableOffset, sp, r8, &nRegReturn ); + return nRegReturn; +} + +namespace +{ + const int codeSnippetSize = 20; + + //some m68k info : http://www2.biglobe.ne.jp/~inaba/trampolines.html + + unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex, + sal_Int32 vtableOffset) + { + unsigned char * p = code; + *(short *)&p[0] = 0x203C; //movel functionIndex,d0 + *(long *)&p[2] = functionIndex; + *(short *)&p[6] = 0x223C; //movel functionIndex,d1 + *(long *)&p[8] = vtableOffset; + *(short *)&p[12] = 0x4EF9; //jmp cpp_vtable_call + *(long *)&p[14] = (long)&cpp_vtable_call; + *(short *)&p[18] = 0x4E71; //nop + return code + codeSnippetSize; + } +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) + { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset); + } + break; + case typelib_TypeClass_INTERFACE_METHOD: + { + (s++)->fn = code + writetoexecdiff; + + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >(member); + + code = codeSnippet(code, functionOffset++, vtableOffset); + break; + } + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * /*beg*/, unsigned char const * /*end*/) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/except.cxx b/bridges/source/cpp_uno/gcc3_linux_m68k/except.cxx new file mode 100644 index 000000000000..1128f0f85cd8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/except.cxx @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + +extern sal_Int32 * pHack; +extern sal_Int32 nHack; + +namespace CPPU_CURRENT_NAMESPACE +{ + void dummy_can_throw_anything( char const * ) + { + } + + //=================================================================== + static OUString toUNOname( char const * p ) SAL_THROW( () ) + { +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif + } + + //===================================================================== + class RTTI + { + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + + public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI(typelib_CompoundTypeDescription *) SAL_THROW( () ); + }; + //____________________________________________________________________ + RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) + { + } + //____________________________________________________________________ + RTTI::~RTTI() SAL_THROW( () ) + { + dlclose( m_hApp ); + } + + //____________________________________________________________________ + type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) + { + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; + } + + //------------------------------------------------------------------ + static void deleteException( void * pExc ) + { + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } + } + + //================================================================== + void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) + { +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + + __cxa_throw( pCppExc, rtti, deleteException ); + } + + static void* getAdjustedPtr(__cxa_exception* header) + { + return header->adjustedPtr; + } + + //=================================================================== + void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) + { + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_m68k/makefile.mk new file mode 100644 index 000000000000..3978bda7cb16 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/makefile.mk @@ -0,0 +1,80 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCLINUX6gcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/except.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/share.hxx b/bridges/source/cpp_uno/gcc3_linux_m68k/share.hxx new file mode 100644 index 000000000000..4ec09c29ff0a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/share.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_m68k/uno2cpp.cxx new file mode 100644 index 000000000000..0d0fd27678eb --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/uno2cpp.cxx @@ -0,0 +1,494 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> +#include <rtl/alloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include <bridges/cpp_uno/shared/bridge.hxx> +#include <bridges/cpp_uno/shared/types.hxx> +#include <bridges/cpp_uno/shared/unointerfaceproxy.hxx> +#include <bridges/cpp_uno/shared/vtables.hxx> + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn) +{ + register float fret asm("fp0"); + register double dret asm("fp0"); + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pRegisterReturn[1] = d1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pRegisterReturn[0] = d0; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = fret; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + default: + break; + } +} + +namespace +{ +//================================================================ + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_uInt32 *pStack, + sal_uInt32 nStack) __attribute__((noinline)); + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_uInt32 *pStack, + sal_uInt32 nStack) +{ + // never called + if (! pThis) + CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + if ( nStack ) + { + // m68k stack is either 2 or 4 bytes aligned, doesn't really matter as + // we deal in 4 byte units anyway + sal_uInt32 nStackBytes = nStack * sizeof(sal_uInt32); + sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes ); + memcpy( stack, pStack, nStackBytes ); + } + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn); + } +#endif + + sal_uInt32 pMethod = *((sal_uInt32*)pThis); + pMethod += 4 * nVtableIndex; + pMethod = *((sal_uInt32 *)pMethod); + + typedef long (*FunctionCall )(); + FunctionCall pFunc = (FunctionCall)pMethod; + + //stick the return area into r8 for big struct returning + asm volatile("movel %0,%%a1" : : "m"(pRegisterReturn) : ); + + long d0 = (*pFunc)(); + + register long d1 asm("d1"); + + MapReturn(d0, d1, eReturnType, (long*)pRegisterReturn); +} +} + +#define INSERT_INT32( pSV, pDS )\ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT64( pSV, pDS )\ + INSERT_INT32( pSV, pDS ) \ + INSERT_INT32( ((sal_uInt32*)pSV)+1, pDS ) + +#define INSERT_FLOAT( pSV, pDS ) \ + INSERT_INT32( pSV, pDS ) + +#define INSERT_DOUBLE( pSV, pDS ) \ + INSERT_INT64( pSV, pDS ) + +#define INSERT_INT16( pSV, pDS ) \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, pDS ) \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +namespace { +//======================================================================= +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + + // max space for: [complex ret ptr], values|ptr ... + sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca( + sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + sal_uInt32 * pStackStart = pStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? __builtin_alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + +// INSERT_INT32( &pCppReturn, pStack ); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + INSERT_INT32( &pAdjustedThisPtr, pStack ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +// uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], + uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], + pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]); +#endif + INSERT_INT64( pCppArgs[nPos], pStack ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "long is %x\n", pCppArgs[nPos]); +#endif + INSERT_INT32( pCppArgs[nPos], pStack ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], pStack ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], pStack ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], pStack ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], pStack ); + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT32( &(pCppArgs[nPos]), pStack ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, + pStackStart, + (pStack - pStackStart)); + + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *> + (pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; + cpp_call( + pThis, aVtableSlot, // get, then set method + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast<typelib_InterfaceMethodTypeDescription const *> + (pMemberDescr))); + + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx new file mode 100644 index 000000000000..f1597c37bac4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx @@ -0,0 +1,805 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/data.h> +#include <osl/endian.h> +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + +using namespace com::sun::star::uno; + +//#define BRDEBUG + +#ifdef BRDEBUG +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +#endif +#include <sys/sysmips.h> + +#ifdef OSL_BIGENDIAN +#define IS_BIG_ENDIAN 1 +#else +#define IS_BIG_ENDIAN 0 +#endif + +using namespace ::com::sun::star::uno; + +namespace +{ + + //================================================================================================== + static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** /*fpreg*/, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + /* Most MIPS ABIs view the arguments as a struct, of which the + first N words go in registers and the rest go on the stack. If I < N, the + Ith word might go in Ith integer argument register or the Ith + floating-point one. For these ABIs, we only need to remember the number + of words passed so far. We are interested only in o32 ABI,so it is the + case. + */ + int nw = 0; // number of words used by arguments + +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call1\n"); +#endif + + /* C++ has [ret *] or this as the first arguments, so no arguments will + * be passed in floating-point registers? + */ + //int int_seen = 0; // have we seen integer arguments? + + void ** pCppStack; //temporary stack pointer + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:simplereturn\n"); +#endif + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + nw++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:complexreturn\n"); +#endif + } + } + + // pop this + gpreg++; + nw++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams); +#endif + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]); +#endif + if (nw < 3) { + if (nw & 1) { + nw++; + gpreg++; + } +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]); +#endif + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + nw += 2; + gpreg += 2; + } else { + if (((long)ovrflw) & 4) ovrflw++; +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]); +#endif + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; + } + break; + + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]); +#endif + if (nw < 4) { + pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN); + pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN); + nw++; + gpreg++; + } else { + pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN); + pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN); + ovrflw++; + } + break; + + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]); +#endif + if (nw < 4) { + pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN); + pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN); + nw++; + gpreg++; + } else { + pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN); + pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN); + ovrflw++; + } + break; + + + default: +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]); +#endif + if (nw < 4) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + nw++; + gpreg++; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:ptr|ref\n"); +#endif + if (nw < 4) { + pCppArgs[nPos] = *(void **)gpreg; + pCppStack = gpreg; + nw++; + gpreg++; + } else { + pCppArgs[nPos] = *(void **)ovrflw; + pCppStack = ovrflw; + ovrflw++; + } +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack); +#endif + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]); +#endif + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]); +#endif + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs); +#endif + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); +#ifdef BRDEBUG + fprintf(stderr,"cpp2uno_call2,after dispatch\n"); +#endif + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } + } + + + //================================================================================================== + static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw); + fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]); +#endif + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + void * pThis; + if (nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset); +#endif + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI); +#endif + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate2\n"); +#endif + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate3\n"); + OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); +#endif + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate4\n"); +#endif + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate5\n"); +#endif + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate51\n"); +#endif + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate52\n"); +#endif + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { +#ifdef BRDEBUG + fprintf(stderr,"cpp_mediate6\n"); +#endif + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; + } + + //================================================================================================== + /** + * is called on incoming vtable calls + * (called by asm snippets) + */ +// static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) +// static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw) + static void cpp_vtable_call(void) + { + int nFunctionIndex; + int vTableOffset; + void** pCallStack; + void** ovrflw; + + sal_Int32 gpreg[4]; + double fpreg[2]; + + //memcpy( fpreg, fpregptr, 16); + + volatile long nRegReturn[2]; + + __asm__( "sw $4, %0\n\t" + "sw $5, %1\n\t" + "sw $6, %2\n\t" + "sw $7, %3\n\t" + ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) ); + + memcpy( gpreg, pCallStack, 16); + +#ifdef BRDEBUG + fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex); + fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset); + fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]); +#endif + + //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; + + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn ); + + switch( aType ) + { + + // move return value into register space + // (will be loaded by machine code snippet) + + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "lbu $2,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "lhu $2,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_SHORT: + __asm__( "lh $2,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + + case typelib_TypeClass_FLOAT: + __asm__( "lwc1 $f0,%0\n\t" : : + "m" (*((float*)nRegReturn)) ); + break; + + case typelib_TypeClass_DOUBLE: + { register double dret asm("$f0"); + dret = (*((double*)nRegReturn)); } + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "lw $3,%0\n\t" : : + "m"(nRegReturn[1]) ); // fall through + + default: + __asm__( "lw $2,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + } + } + + + int const codeSnippetSize = 56; + + unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) + { + +#ifdef BRDEBUG + fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex); + fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset); + fflush(stderr); +#endif + + if (! simpleRetType ) + functionIndex |= 0x80000000; + + unsigned long * p = (unsigned long *) code; + + // OSL_ASSERT( sizeof (long) == 4 ); + OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake + + /* generate this code */ + /* + #save regs into argument space required by mips abi + c: afa40000 sw a0,0(sp) + 10: afa50004 sw a1,4(sp) + 14: afa60008 sw a2,8(sp) + 18: afa7000c sw a3,12(sp) + #a0=index + 1c: 3c040000 lui a0,0x0 + 20: 34840000 ori a0,a0,0x0 + #a1=offset + 24: 3c050000 lui a1,0x0 + 28: 34a50000 ori a1,a1,0x0 + #a2=gpregptr + 2c: 27a60000 addiu a2,sp,0 + #a3=ovrflw + 30: 27a70010 addiu a3,sp,16 + #load cpp_vtable_call addr + 34: 3c190000 lui t9,0x0 + 38: 37390000 ori t9,t9,0 + #jmp to the function,note: we don't use jalr, that will destroy $ra + #but be sure to use t9! gp calculation depends on it + 3c: 03200008 jr t9 + 40: 00000000 nop + + be careful, we use the argument space reserved by the caller to + write down regs. This can avoid the need to make use of arbitary far away + stack space or to allocate a function frame for this code snippet itself. + Since only functions with variable arguments will overwrite the space, + cpp_vtable_call should be safe. + ??? gcc seems change this behavior! cpp_vtable_call overwrite the space! + */ + + * p++ = 0xafa40000; + * p++ = 0xafa50004; + * p++ = 0xafa60008; + * p++ = 0xafa7000c; + * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff); + * p++ = 0x34840000 | (functionIndex & 0x0000ffff); + * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff); + * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff); + * p++ = 0x27a60000; + * p++ = 0x27a70010; + * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff); + * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); + * p++ = 0x03200008; + * p++ = 0x00000000; + return (code + codeSnippetSize); + + } + + +} + + +#define MIN_LINE_SIZE 32 + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/) +{ + sysmips(FLUSH_CACHE,0,0,0); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; //null + slots[-1].fn = 0; //destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; +#ifdef BRDEBUG + fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset); + fprintf(stderr, "nMembers=%d\n",type->nMembers); + fflush(stderr); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/except.cxx b/bridges/source/cpp_uno/gcc3_linux_mips/except.cxx new file mode 100644 index 000000000000..f4c4e24c4374 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/except.cxx @@ -0,0 +1,327 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if defined BRIDGES_DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if defined BRIDGES_DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if defined BRIDGES_DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if defined BRIDGES_DEBUG + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if defined BRIDGES_DEBUG + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_mips/makefile.mk new file mode 100644 index 000000000000..f71750e9108d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)" == "GCCLINUXM" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +CFLAGSNOOPT=-O0 + +NOOPTFILES = \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + + +SHL1TARGET=$(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map + +SHL1OBJS= $(SLOFILES) +SHL1LIBS =$(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/share.hxx b/bridges/source/cpp_uno/gcc3_linux_mips/share.hxx new file mode 100644 index 000000000000..4ec09c29ff0a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/share.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_mips/uno2cpp.cxx new file mode 100644 index 000000000000..4507206f2508 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/uno2cpp.cxx @@ -0,0 +1,599 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +//#define BRDEBUG +#ifdef BRDEBUG +#include <stdio.h> +#endif + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + + + //================================================================================================== + static void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + char * pPT, + sal_Int32 * pStackLongs, + sal_Int32 /*nStackLongs*/) + { + + // parameter list is mixed list of * and values + // reference parameters are pointers + + unsigned long * mfunc; // actual function to be invoked + void (*ptr)(); + int gpr[4]; // storage for gpregisters, map to a0-a3 + int off; // offset used to find function + int nw; // number of words mapped + long *p; // pointer to parameter overflow area + int c; // character of parameter type being decoded + int iret, iret2; // temporary function return values + + // never called + if (! pAdjustedThisPtr ) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + +#ifdef BRDEBUG + fprintf(stderr,"in CallVirtualMethod\n"); +#endif + + // Because of the MIPS O32 calling conventions we could be passing + // parameters in both register types and on the stack. To create the + // stack parameter area we need we now simply allocate local + // variable storage param[] that is at least the size of the parameter stack + // (more than enough space) which we can overwrite the parameters into. + + /* p = sp - 512; new sp will be p - 16, but we don't change sp + * at this time to avoid breaking ABI--not sure whether changing sp will break + * references to local variables. For the same reason, we use abosulte value. + */ + __asm__ __volatile__ ( + "addiu $2,$29,-512\n\t" + "move %0,$2\n\t" + :"=r"(p): : "$2","$29" ); + +#ifdef BRDEBUG + if (nStackLongs * 4 > 512 ) + fprintf(stderr,"too many arguments"); +#endif + + // now begin to load the C++ function arguments into storage + nw = 0; + + // now we need to parse the entire signature string */ + // until we get the END indicator */ + + // treat complex return pointer like any other parameter // + +#ifdef BRDEBUG + fprintf(stderr,"overflow area pointer p=%p\n",p); + + /* Let's figure out what is really going on here*/ + fprintf(stderr,"callVirtualMethod paramters string is %s\n",pPT); + int k = nStackLongs; + long * q = (long *)pStackLongs; + while (k > 0) { + fprintf(stderr,"uno stack is: %x\n",(unsigned int)*q); + k--; + q++; + } +#endif + + /* parse the argument list up to the ending ) */ + while (*pPT != 'X') { + c = *pPT; + switch (c) { + case 'D': /* type is double */ + /* treat the same as long long */ + case 'H': /* type is long long */ + if (nw & 1) nw++; /* note even elements gpr[] will map to + odd registers*/ + if (nw < 4) { + gpr[nw++] = *pStackLongs; + gpr[nw++] = *(pStackLongs+1); + } else { + if (((long) p) & 4) + p++; + *p++ = *pStackLongs; + *p++ = *(pStackLongs+1); + } + pStackLongs += 2; + break; + + case 'S': + if (nw < 4) { + gpr[nw++] = *((unsigned short*)pStackLongs); + } else { + *p++ = *((unsigned short *)pStackLongs); + } + pStackLongs += 1; + break; + + case 'B': + if (nw < 4) { + gpr[nw++] = *((char *)pStackLongs); + } else { + *p++ = *((char *)pStackLongs); + } + pStackLongs += 1; + break; + + default: + if (nw < 4) { + gpr[nw++] = *pStackLongs; + } else { + *p++ = *pStackLongs; + } + pStackLongs += 1; + break; + } + pPT++; + } + + /* figure out the address of the function we need to invoke */ + off = nVtableIndex; + off = off * 4; // 4 bytes per slot + mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable + mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset + mfunc = *((unsigned long **)mfunc); // the function is stored at the address + ptr = (void (*)())mfunc; + +#ifdef BRDEBUG + fprintf(stderr,"calling function %p\n",mfunc); +#endif + + /* Set up the machine registers and invoke the function */ + + __asm__ __volatile__ ( + "lw $4, 0(%0)\n\t" + "lw $5, 4(%0)\n\t" + "lw $6, 8(%0)\n\t" + "lw $7, 12(%0)\n\t" + : : "r" (gpr) + : "$4", "$5", "$6", "$7" + ); + + __asm__ __volatile__ ("addiu $29,$29,-528\r\n":::"$29"); + + (*ptr)(); + + __asm__ __volatile__ ("addiu $29,$29,528\r\n":::"$29"); + + __asm__ __volatile__ ( + "sw $2,%0 \n\t" + "sw $3,%1 \n\t" + : "=m" (iret), "=m" (iret2) : ); + register float fret asm("$f0"); + register double dret asm("$f0"); + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = iret2; // fall through + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = iret; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)iret; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)iret; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = fret; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + default: + break; + } + } + + + //================================================================================================== + static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) + { + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // need to know parameter types for callVirtualMethod so generate a signature string + char * pParamType = (char *) alloca(nParams+2); + char * pPT = pParamType; + +#ifdef BRDEBUG + fprintf(stderr,"in cpp_call\n"); +#endif + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + // OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = + (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ): pUnoReturn); // direct way + *pPT++ = 'I'; //signify that a complex return type on stack + pCppStack += sizeof(void *); + } + } + // push this + void* pAdjustedThisPtr = reinterpret_cast< void **>(pThis->getCppI()) + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + *pPT++ = 'I'; + + // stack space + // OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + + // we need to know type of each param so that we know whether to use + // gpr or fpr to pass in parameters: + // Key: I - int, long, pointer, etc means pass in gpr + // B - byte value passed in gpr + // S - short value passed in gpr + // F - float value pass in fpr + // D - double value pass in fpr + // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc + // X - indicates end of parameter description string + + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pPT++ = 'I'; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + *pPT++ = 'S'; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *pPT++ = 'B'; + break; + case typelib_TypeClass_FLOAT: + *pPT++ = 'F'; + break; + case typelib_TypeClass_DOUBLE: + *pPT++ = 'D'; + pCppStack += sizeof(sal_Int32); // extra long + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pPT++ = 'H'; + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // KBH: FIXME: is this the right way to pass these + *pPT++='I'; + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // terminate the signature string + *pPT++='X'; + *pPT=0; + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } + +} + + +namespace bridges { namespace cpp_uno { namespace shared { + +//================================================================================================== +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + //typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + +#ifdef BRDEBUG + fprintf(stderr,"in dispatch\n"); +#endif + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx new file mode 100644 index 000000000000..bc9702351464 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx @@ -0,0 +1,795 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <string.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + + +using namespace ::com::sun::star::uno; + +namespace +{ + +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + int ng = 0; //number of gpr registers used +#ifndef __NO_FPRS__ + int nf = 0; //number of fpr regsiters used +#endif + void ** pCppStack; //temporary stack pointer + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + ng++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + ng++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + + switch (pParamTypeDescr->eTypeClass) + { + + case typelib_TypeClass_DOUBLE: +#ifndef __NO_FPRS__ + if (nf < 8) { + pCppArgs[nPos] = fpreg; + pUnoArgs[nPos] = fpreg; + nf++; + fpreg += 2; +#else + if (ng & 1) { + ng++; + gpreg++; + } + if (ng < 8) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng += 2; + gpreg += 2; +#endif + } else { + if (((long)ovrflw) & 4) ovrflw++; + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; + } + break; + + case typelib_TypeClass_FLOAT: + // fpreg are all double values so need to + // modify fpreg to be a single word float value +#ifndef __NO_FPRS__ + if (nf < 8) { + float tmp = (float) (*((double *)fpreg)); + (*((float *) fpreg)) = tmp; + pCppArgs[nPos] = fpreg; + pUnoArgs[nPos] = fpreg; + nf++; + fpreg += 2; +#else + if (ng < 8) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng++; + gpreg++; +#endif + } else { +#if 0 /* abi is not being followed correctly */ + if (((long)ovrflw) & 4) ovrflw++; + float tmp = (float) (*((double *)ovrflw)); + (*((float *) ovrflw)) = tmp; + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; +#else + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 1; +#endif + } + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (ng & 1) { + ng++; + gpreg++; + } + if (ng < 8) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng += 2; + gpreg += 2; + } else { + if (((long)ovrflw) & 4) ovrflw++; + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; + } + break; + + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (ng < 8) { + pCppArgs[nPos] = (((char *)gpreg) + 3); + pUnoArgs[nPos] = (((char *)gpreg) + 3); + ng++; + gpreg++; + } else { + pCppArgs[nPos] = (((char *)ovrflw) + 3); + pUnoArgs[nPos] = (((char *)ovrflw) + 3); + ovrflw++; + } + break; + + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (ng < 8) { + pCppArgs[nPos] = (((char *)gpreg)+ 2); + pUnoArgs[nPos] = (((char *)gpreg)+ 2); + ng++; + gpreg++; + } else { + pCppArgs[nPos] = (((char *)ovrflw) + 2); + pUnoArgs[nPos] = (((char *)ovrflw) + 2); + ovrflw++; + } + break; + + + default: + if (ng < 8) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng++; + gpreg++; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + + if (ng < 8) { + pCppArgs[nPos] = *(void **)gpreg; + pCppStack = gpreg; + ng++; + gpreg++; + } else { + pCppArgs[nPos] = *(void **)ovrflw; + pCppStack = ovrflw; + ovrflw++; + } + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + void * pThis; + if (nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) +{ + sal_Int32 gpreg[8]; + memcpy( gpreg, gpregptr, 32); + +#ifndef __NO_FPRS__ + double fpreg[8]; + memcpy( fpreg, fpregptr, 64); +#endif + + volatile long nRegReturn[2]; + + // fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %x\n",nFunctionIndex); + // fprintf(stderr,"in cpp_vtable_call nVtableOffset is %x\n",nVtableOffset); + // fflush(stderr); + + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, +#ifndef __NO_FPRS__ + (void**)fpreg, +#else + NULL, +#endif + ovrflw, (sal_Int64*)nRegReturn ); + + switch( aType ) + { + + // move return value into register space + // (will be loaded by machine code snippet) + + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "lbz 3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "lhz 3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_FLOAT: +#ifndef __NO_FPRS__ + __asm__( "lfs 1,%0\n\t" : : + "m" (*((float*)nRegReturn)) ); + #else + __asm__( "lwz 3,%0\n\t" : : + "m"(nRegReturn[0]) ); +#endif + break; + + case typelib_TypeClass_DOUBLE: +#ifndef __NO_FPRS__ + __asm__( "lfd 1,%0\n\t" : : + "m" (*((double*)nRegReturn)) ); +#else + __asm__( "lwz 3,%0\n\t" : : + "m"(nRegReturn[0]) ); + __asm__( "lwz 4,%0\n\t" : : + "m"(nRegReturn[1]) ); +#endif + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "lwz 4,%0\n\t" : : + "m"(nRegReturn[1]) ); // fall through + + default: + __asm__( "lwz 3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + } +} + + +int const codeSnippetSize = 108; + +unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) +{ + + // fprintf(stderr,"in codeSnippet functionIndex is %x\n", functionIndex); + // fprintf(stderr,"in codeSnippet vtableOffset is %x\n", vtableOffset); + // fflush(stderr); + + if (! simpleRetType ) + functionIndex |= 0x80000000; + + unsigned long * p = (unsigned long *) code; + + // OSL_ASSERT( sizeof (long) == 4 ); + OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake + + /* generate this code */ + // # so first save gpr 3 to gpr 10 (aligned to 4) + // stw r3,-2048(r1) + // stw r4,-2044(r1) + // stw r5,-2040(r1) + // stw r6,-2036(r1) + // stw r7,-2032(r1) + // stw r8,-2028(r1) + // stw r9,-2024(r1) + // stw r10,-2020(r1) + + + // # next save fpr 1 to fpr 8 (aligned to 8) + // if dedicated floating point registers are used + // stfd f1,-2016(r1) + // stfd f2,-2008(r1) + // stfd f3,-2000(r1) + // stfd f4,-1992(r1) + // stfd f5,-1984(r1) + // stfd f6,-1976(r1) + // stfd f7,-1968(r1) + // stfd f8,-1960(r1) + + // # now here is where cpp_vtable_call must go + // lis r3,-8531 + // ori r3,r3,48879 + // mtctr r3 + + // # now load up the functionIndex + // lis r3,-8531 + // ori r3,r3,48879 + + // # now load up the vtableOffset + // lis r4,-8531 + // ori r4,r4,48879 + + // #now load up the pointer to the saved gpr registers + // addi r5,r1,-2048 + + // #now load up the pointer to the saved fpr registers + // addi r6,r1,-2016 + // if no dedicated floating point registers are used than we have NULL + // pointer there + // li r6, 0 + // + + // #now load up the pointer to the overflow call stack + // addi r7,r1,8 + // bctr + + * p++ = 0x9061f800; + * p++ = 0x9081f804; + * p++ = 0x90a1f808; + * p++ = 0x90c1f80c; + * p++ = 0x90e1f810; + * p++ = 0x9101f814; + * p++ = 0x9121f818; + * p++ = 0x9141f81c; +#ifndef __NO_FPRS__ + * p++ = 0xd821f820; + * p++ = 0xd841f828; + * p++ = 0xd861f830; + * p++ = 0xd881f838; + * p++ = 0xd8a1f840; + * p++ = 0xd8c1f848; + * p++ = 0xd8e1f850; + * p++ = 0xd901f858; +#else + /* these nops could be replaced with a smaller codeSnippetSize - 8 * 4 */ + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; + * p++ = 0x60000000; +#endif + * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16); + * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); + * p++ = 0x7c6903a6; + * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16); + * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF); + * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16); + * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF); + * p++ = 0x38a1f800; +#ifndef __NO_FPRS__ + * p++ = 0x38c1f820; +#else + * p++ = 0x38c00000; +#endif + * p++ = 0x38e10008; + * p++ = 0x4e800420; + return (code + codeSnippetSize); + +} + + +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) +{ + int const lineSize = 32; + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("sync" : : : "memory"); + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("isync" : : : "memory"); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); + // fflush(stderr); + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/except.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_powerpc/makefile.mk new file mode 100644 index 000000000000..9a752009904e --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/makefile.mk @@ -0,0 +1,80 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +.IF "$(COM)$(OS)$(CPU)$(COMNAME)$(CPUNAME)" == "GCCLINUXPgcc3POWERPC" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj + + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS= $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/share.hxx b/bridges/source/cpp_uno/gcc3_linux_powerpc/share.hxx new file mode 100644 index 000000000000..4ec09c29ff0a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/share.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc/uno2cpp.cxx new file mode 100644 index 000000000000..49a33f6d12ae --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/uno2cpp.cxx @@ -0,0 +1,675 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + + +//================================================================================================== +static void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + char * pPT, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs) +{ + + // parameter list is mixed list of * and values + // reference parameters are pointers + + // the basic idea here is to use gpr[8] as a storage area for + // the future values of registers r3 to r10 needed for the call, + // and similarly fpr[8] as a storage area for the future values + // of floating point registers f1 to f8 + + unsigned long * mfunc; // actual function to be invoked + void (*ptr)(); + int gpr[8]; // storage for gpregisters, map to r3-r10 + int off; // offset used to find function +#ifndef __NO_FPRS__ + double fpr[8]; // storage for fpregisters, map to f1-f8 + int f; // number of fprs mapped so far + double dret; // temporary function return values +#endif + int n; // number of gprs mapped so far + long *p; // pointer to parameter overflow area + int c; // character of parameter type being decoded + int iret, iret2; + + // Because of the Power PC calling conventions we could be passing + // parameters in both register types and on the stack. To create the + // stack parameter area we need we now simply allocate local + // variable storage param[] that is at least the size of the parameter stack + // (more than enough space) which we can overwrite the parameters into. + + // Note: This keeps us from having to decode the signature twice and + // prevents problems with later local variables. + + // Note: could require up to 2*nStackLongs words of parameter stack area + // if the call has many float parameters (i.e. floats take up only 1 + // word on the stack but double takes 2 words in parameter area in the + // stack frame . + + // Update! floats on the outgoing parameter stack only take up 1 word + // (stfs is used) which is not correct according to the ABI but we + // will match what the compiler does until this is figured out + + // this grows the current stack to the appropriate size + // and sets the outgoing stack pointer p to the right place + __asm__ __volatile__ ( + "rlwinm %0,%0,3,3,28\n\t" + "addi %0,%0,22\n\t" + "rlwinm %0,%0,0,4,28\n\t" + "lwz 0,0(1)\n\t" + "subf 1,%0,1\n\t" + "stw 0,0(1)\n\t" + : : "r" (nStackLongs) : "0" ); + + __asm__ __volatile__ ( "addi %0,1,8" : "=r" (p) : ); + + // never called + // if (! pAdjustedThisPtr ) dummy_can_throw_anything("xxx"); // address something + + + // now begin to load the C++ function arguments into storage + n = 0; +#ifndef __NO_FPRS__ + f = 0; +#endif + + // now we need to parse the entire signature string */ + // until we get the END indicator */ + + // treat complex return pointer like any other parameter // + +#if 0 + /* Let's figure out what is really going on here*/ + fprintf(stderr,"callVirtualMethod paramters string is %s\n",pPT); + int k = nStackLongs; + long * q = (long *)pStackLongs; + while (k > 0) { + fprintf(stderr,"uno stack is: %x\n",*q); + k--; + q++; + } +#endif + + /* parse the argument list up to the ending ) */ + while (*pPT != 'X') { + c = *pPT; + switch (c) { + case 'D': /* type is double */ +#ifndef __NO_FPRS__ + if (f < 8) { + fpr[f++] = *((double *)pStackLongs); /* store in register */ +#else + if (n & 1) + n++; + if (n < 8) { + gpr[n++] = *pStackLongs; + gpr[n++] = *(pStackLongs+1); +#endif + } else { + if (((long) p) & 4) + p++; + *p++ = *pStackLongs; /* or on the parameter stack */ + *p++ = *(pStackLongs + 1); + } + pStackLongs += 2; + break; + + case 'F': /* type is float */ + /* this assumes that floats are stored as 1 32 bit word on param + stack and that if passed in parameter stack to C, should be + as double word. + + Whoops: the abi is not actually followed by gcc, need to + store floats as a *single* word on outgoing parameter stack + to match what gcc actually does + */ +#ifndef __NO_FPRS__ + if (f < 8) { + fpr[f++] = *((float *)pStackLongs); +#else + if (n < 8) { + gpr[n++] = *pStackLongs; +#endif + } else { +#if 0 /* if abi were followed */ + if (((long) p) & 4) + p++; + *((double *)p) = *((float *)pStackLongs); + p += 2; +#else + *((float *)p) = *((float *)pStackLongs); + p += 1; +#endif + } + pStackLongs += 1; + break; + + case 'H': /* type is long long */ + if (n & 1) n++; /* note even elements gpr[] will map to + odd registers*/ + if (n <= 6) { + gpr[n++] = *pStackLongs; + gpr[n++] = *(pStackLongs+1); + } else { + if (((long) p) & 4) + p++; + *p++ = *pStackLongs; + *p++ = *(pStackLongs+1); + } + pStackLongs += 2; + break; + + case 'S': + if (n < 8) { + gpr[n++] = *((unsigned short*)pStackLongs); + } else { + *p++ = *((unsigned short *)pStackLongs); + } + pStackLongs += 1; + break; + + case 'B': + if (n < 8) { + gpr[n++] = *((char *)pStackLongs); + } else { + *p++ = *((char *)pStackLongs); + } + pStackLongs += 1; + break; + + default: + if (n < 8) { + gpr[n++] = *pStackLongs; + } else { + *p++ = *pStackLongs; + } + pStackLongs += 1; + break; + } + pPT++; + } + + /* figure out the address of the function we need to invoke */ + off = nVtableIndex; + off = off * 4; // 4 bytes per slot + mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable + mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset + mfunc = *((unsigned long **)mfunc); // the function is stored at the address + ptr = (void (*)())mfunc; + + /* Set up the machine registers and invoke the function */ + + __asm__ __volatile__ ( + "lwz 3, 0(%0)\n\t" + "lwz 4, 4(%0)\n\t" + "lwz 5, 8(%0)\n\t" + "lwz 6, 12(%0)\n\t" + "lwz 7, 16(%0)\n\t" + "lwz 8, 20(%0)\n\t" + "lwz 9, 24(%0)\n\t" + "lwz 10, 28(%0)\n\t" +#ifndef __NO_FPRS__ + "lfd 1, 0(%1)\n\t" + "lfd 2, 8(%1)\n\t" + "lfd 3, 16(%1)\n\t" + "lfd 4, 24(%1)\n\t" + "lfd 5, 32(%1)\n\t" + "lfd 6, 40(%1)\n\t" + "lfd 7, 48(%1)\n\t" + "lfd 8, 56(%1)\n\t" + : : "r" (gpr), "r" (fpr) +#else + : : "r" (gpr) +#endif + : "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" + ); + + (*ptr)(); + + __asm__ __volatile__ ( + "mr %0, 3\n\t" + "mr %1, 4\n\t" +#ifndef __NO_FPRS__ + "fmr %2, 1\n\t" + : "=r" (iret), "=r" (iret2), "=f" (dret) +#else + : "=r" (iret), "=r" (iret2) +#endif + : ); + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[0] = iret; + ((long*)pRegisterReturn)[1] = iret2; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = iret; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)iret; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)iret; + break; + case typelib_TypeClass_FLOAT: +#ifndef __NO_FPRS__ + *(float*)pRegisterReturn = (float)dret; +#else + ((unsigned int*)pRegisterReturn)[0] = iret; +#endif + break; + case typelib_TypeClass_DOUBLE: +#ifndef __NO_FPRS__ + *(double*)pRegisterReturn = dret; +#else + ((unsigned int*)pRegisterReturn)[0] = iret; + ((unsigned int*)pRegisterReturn)[1] = iret2; +#endif + break; + default: + break; + } +} + + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // need to know parameter types for callVirtualMethod so generate a signature string + char * pParamType = (char *) alloca(nParams+2); + char * pPT = pParamType; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + // OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = + (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ): pUnoReturn); // direct way + *pPT++ = 'I'; //signify that a complex return type on stack + pCppStack += sizeof(void *); + } + } + // push this + void* pAdjustedThisPtr = reinterpret_cast< void **>(pThis->getCppI()) + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + *pPT++ = 'I'; + + // stack space + // OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + + // we need to know type of each param so that we know whether to use + // gpr or fpr to pass in parameters: + // Key: I - int, long, pointer, etc means pass in gpr + // B - byte value passed in gpr + // S - short value passed in gpr + // F - float value pass in fpr + // D - double value pass in fpr + // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc + // X - indicates end of parameter description string + + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pPT++ = 'I'; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + *pPT++ = 'S'; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *pPT++ = 'B'; + break; + case typelib_TypeClass_FLOAT: + *pPT++ = 'F'; + break; + case typelib_TypeClass_DOUBLE: + *pPT++ = 'D'; + pCppStack += sizeof(sal_Int32); // extra long + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pPT++ = 'H'; + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // KBH: FIXME: is this the right way to pass these + *pPT++='I'; + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // terminate the signature string + *pPT++='X'; + *pPT=0; + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx new file mode 100644 index 000000000000..e9a5e8c6bb8b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx @@ -0,0 +1,723 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include <stdio.h> +#include <string.h> + + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "as far as cpp2uno_call\n"); +#endif + + int ng = 0; //number of gpr registers used + int nf = 0; //number of fpr regsiters used + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + ng++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + ng++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + bool bOverFlowUsed = false; + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple\n"); +#endif + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + if (nf < ppc64::MAX_SSE_REGS) + { + if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT) + { + float tmp = (float) (*((double *)fpreg)); + (*((float *) fpreg)) = tmp; + } + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++; + nf++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (ng < ppc64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-1)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-1)); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (ng < ppc64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-2)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-2)); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (ng < ppc64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-4)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-4)); + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + default: + if (ng < ppc64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex, ng is %d\n", ng); +#endif + void *pCppStack; //temporary stack pointer + + if (ng < ppc64::MAX_GPR_REGS) + { + pCppArgs[nPos] = pCppStack = *gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pCppStack = *ovrflw; + bOverFlowUsed = true; + } + if (bOverFlowUsed) ovrflw++; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of params\n"); +#endif + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_uInt64 nOffsetAndIndex, + void ** gpreg, void ** fpreg, long sp, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" ); + + sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32); + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); + + long sf = *(long*)sp; + void ** ovrflw = (void**)(sf + 112); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + void * pThis; + if (nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is gpreg[0]\n"); +#endif + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is %lx\n", pThis); +#endif + + pThis = static_cast< char * >(pThis) - nVtableOffset; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pThis is now %lx\n", pThis); +#endif + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "indexes are %d %d\n", nFunctionIndex, pTypeDescr->nMapFunctionIndexToMemberIndex); +#endif + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "members are %d %d\n", nMemberPos, pTypeDescr->nAllMembers); +#endif + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "screwed\n"); +#endif + + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of cpp_mediate\n"); +#endif + return eRet; +} + +extern "C" void privateSnippetExecutor( ... ) +{ + volatile long nOffsetAndIndex; + + //mr %r3, %r11 # move into arg1 the 64bit value passed from OOo + __asm__ __volatile__ ( + "mr %0, 11\n\t" + : "=r" (nOffsetAndIndex) : ); + + sal_uInt64 gpreg[ppc64::MAX_GPR_REGS]; + double fpreg[ppc64::MAX_SSE_REGS]; + + __asm__ __volatile__ ( + "std 3, 0(%0)\t\n" + "std 4, 8(%0)\t\n" + "std 5, 16(%0)\t\n" + "std 6, 24(%0)\t\n" + "std 7, 32(%0)\t\n" + "std 8, 40(%0)\t\n" + "std 9, 48(%0)\t\n" + "std 10, 56(%0)\t\n" + "stfd 1, 0(%1)\t\n" + "stfd 2, 8(%1)\t\n" + "stfd 3, 16(%1)\t\n" + "stfd 4, 24(%1)\t\n" + "stfd 5, 32(%1)\t\n" + "stfd 6, 40(%1)\t\n" + "stfd 7, 48(%1)\t\n" + "stfd 8, 56(%1)\t\n" + "stfd 9, 64(%1)\t\n" + "stfd 10, 72(%1)\t\n" + "stfd 11, 80(%1)\t\n" + "stfd 12, 88(%1)\t\n" + "stfd 13, 96(%1)\t\n" + : : "r" (gpreg), "r" (fpreg) + : "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", "fr8", "fr9", + "fr10", "fr11", "fr12", "fr13" + ); + + volatile long sp; + + //stack pointer + __asm__ __volatile__ ( + "mr %0, 1\n\t" + : "=r" (sp) : ); + + volatile long nRegReturn[1]; + + typelib_TypeClass aType = + cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, sp, (sal_Int64*)nRegReturn); + + switch( aType ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "lbz 3,%0\n\t" + : : "m" (nRegReturn[0]) ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "lhz 3,%0\n\t" + : : "m" (nRegReturn[0]) ); + break; + case typelib_TypeClass_SHORT: + __asm__( "lha 3,%0\n\t" + : : "m" (nRegReturn[0]) ); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + __asm__( "lwz 3,%0\n\t" + : : "m"(nRegReturn[0]) ); + break; + case typelib_TypeClass_LONG: + __asm__( "lwa 3,%0\n\t" + : : "m"(nRegReturn[0]) ); + break; + case typelib_TypeClass_FLOAT: + __asm__( "lfs 1,%0\n\t" + : : "m" (*((float*)nRegReturn)) ); + break; + case typelib_TypeClass_DOUBLE: + __asm__( "lfd 1,%0\n\t" + : : "m" (*((double*)nRegReturn)) ); + break; + default: + __asm__( "ld 3,%0\n\t" + : : "m" (nRegReturn[0]) ); + break; + } +} + +const int codeSnippetSize = 24; + +unsigned char * codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + bool simpleRetType) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr,"in codeSnippet functionIndex is %x\n", nFunctionIndex); + fprintf(stderr,"in codeSnippet vtableOffset is %x\n", nVtableOffset); +#endif + + sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex ); + + if ( !simpleRetType ) + nOffsetAndIndex |= 0x80000000; + + void ** raw = (void **)&code[0]; + memcpy(raw, (char*) privateSnippetExecutor, 16); + raw[2] = (void*) nOffsetAndIndex; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in: offset/index is %x %x %d, %lx\n", + nFunctionIndex, nVtableOffset, !simpleRetType, raw[2]); +#endif + return (code + codeSnippetSize); +} + +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) +{ + int const lineSize = 32; + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("sync" : : : "memory"); + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("isync" : : : "memory"); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/except.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_powerpc64/makefile.mk new file mode 100644 index 000000000000..77763d7c8b54 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/makefile.mk @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)$(CPUNAME)" == "GCCLINUXPgcc3POWERPC64" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map + +SHL1OBJS= $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx new file mode 100644 index 000000000000..38ed48ee06c8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace ppc64 +{ + enum ppclimits { MAX_GPR_REGS = 8, MAX_SSE_REGS = 13 }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx new file mode 100644 index 000000000000..66db74288cb3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx @@ -0,0 +1,602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(long r3, double dret, typelib_TypeClass eTypeClass, void *pRegisterReturn) +{ + switch (eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = r3; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = r3; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = (unsigned short)r3; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = (unsigned char)r3; + break; + case typelib_TypeClass_FLOAT: + *reinterpret_cast<float *>( pRegisterReturn ) = dret; + break; + case typelib_TypeClass_DOUBLE: + *reinterpret_cast<double *>( pRegisterReturn ) = dret; + break; + default: + break; + } +} + +namespace +{ +//================================================================================================== +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ + // Stack, if used, must be 16-bytes aligned + if ( nStack ) + nStack = ( nStack + 1 ) & ~1; + + // Should not happen, but... + if ( nFPR > ppc64::MAX_SSE_REGS ) + nFPR = ppc64::MAX_SSE_REGS; + if ( nGPR > ppc64::MAX_GPR_REGS ) + nGPR = ppc64::MAX_GPR_REGS; + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( int i = 0; i < nFPR; ++i ) + fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + } +#endif + + // Load parameters to stack, if necessary + sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 ); + memcpy( stack, pStack, nStack * 8 ); + + // Get pointer to method + sal_uInt64 pMethod = *((sal_uInt64 *)pThis); + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + volatile double dret; + + // fill registers + __asm__ __volatile__ ( + "ld 3, 0(%0)\n\t" + "ld 4, 8(%0)\n\t" + "ld 5, 16(%0)\n\t" + "ld 6, 24(%0)\n\t" + "ld 7, 32(%0)\n\t" + "ld 8, 40(%0)\n\t" + "ld 9, 48(%0)\n\t" + "ld 10, 56(%0)\n\t" + "lfd 1, 0(%1)\n\t" + "lfd 2, 8(%1)\n\t" + "lfd 3, 16(%1)\n\t" + "lfd 4, 24(%1)\n\t" + "lfd 5, 32(%1)\n\t" + "lfd 6, 40(%1)\n\t" + "lfd 7, 48(%1)\n\t" + "lfd 8, 56(%1)\n\t" + "lfd 9, 64(%1)\n\t" + "lfd 10, 72(%1)\n\t" + "lfd 11, 80(%1)\n\t" + "lfd 12, 88(%1)\n\t" + "lfd 13, 96(%1)\n\t" + : : "r" (pGPR), "r" (pFPR) + : "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", "fr8", "fr9", + "fr10", "fr11", "fr12", "fr13" + ); + + // tell gcc that r3 to r11 are not available to it for doing the TOC and exception munge on the func call + register sal_uInt64 r3 asm("r3"); + register sal_uInt64 r4 asm("r4"); + register sal_uInt64 r5 asm("r5"); + register sal_uInt64 r6 asm("r6"); + register sal_uInt64 r7 asm("r7"); + register sal_uInt64 r8 asm("r8"); + register sal_uInt64 r9 asm("r9"); + register sal_uInt64 r10 asm("r10"); + register sal_uInt64 r11 asm("r11"); + + (*pFunc)(r3, r4, r5, r6, r7, r8, r9, r10); + + // get return value + __asm__ __volatile__ ( + "mr %1, 3\n\t" + "mr %2, 4\n\t" + "fmr %0, 1\n\t" + : "=f" (dret), "=r" (r3), "=r" (r4) : ); + + MapReturn(r3, dret, pReturnTypeDescr->eTypeClass, pRegisterReturn); +} + +// Macros for easier insertion of values to registers or stack +// pSV - pointer to the source +// nr - order of the value [will be increased if stored to register] +// pFPR, pGPR - pointer to the registers +// pDS - pointer to the stack [will be increased if stored here] + +// The value in %xmm register is already prepared to be retrieved as a float, +// thus we treat float and double the same +#define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_SSE_REGS ) \ + pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_SSE_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_INT64( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \ + if ( nr < ppc64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + bOverFlow = true; \ + if (bOverFlow) \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; + + sal_uInt64 pGPR[ppc64::MAX_GPR_REGS]; + sal_uInt32 nGPR = 0; + + double pFPR[ppc64::MAX_SSE_REGS]; + sal_uInt32 nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + bool bOverFlow = false; + + if (pReturnTypeDescr) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass); +#endif + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple return\n"); +#endif + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "pCppReturn/pUnoReturn is %lx/%lx", pCppReturn, pUnoReturn); +#endif + INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack, bOverFlow ); + } + } + // push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "this pointer is %p\n", pAdjustedThisPtr); +#endif + INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow ); + + // Args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "n params is %d\n", nParams); +#endif + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "param %d is %d %d %d\n", nPos, rParam.bOut, bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ), + pParamTypeDescr->eTypeClass); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +// uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]); +#endif + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "long is %x\n", pCppArgs[nPos]); +#endif + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack, bOverFlow ); + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex type again %d\n", rParam.bIn); +#endif + if (! rParam.bIn) // is pure out + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex size is %d\n", pParamTypeDescr->nSize ); +#endif + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "this one\n"); +#endif + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "that one, passing %lx through\n", pUnoArgs[nPos]); +#endif + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, + pStackStart, ( pStack - pStackStart ), + pGPR, nGPR, + pFPR, nFPR ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx new file mode 100644 index 000000000000..a29b7c38dba7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx @@ -0,0 +1,696 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include <stdio.h> +#include <string.h> + +using namespace ::com::sun::star::uno; + +namespace +{ + +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + int ng = 0; //number of gpr registers used + int nf = 0; //number of fpr regsiters used + void ** pCppStack; //temporary stack pointer + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + ng++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + ng++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { + + switch (pParamTypeDescr->eTypeClass) + { + + case typelib_TypeClass_DOUBLE: + if (nf < 2) { + pCppArgs[nPos] = fpreg; + pUnoArgs[nPos] = fpreg; + nf++; + fpreg += 2; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; + } + break; + + case typelib_TypeClass_FLOAT: + // fpreg are all double values so need to + // modify fpreg to be a single word float value + if (nf < 2) { +// float tmp = (float) (*((double *)fpreg)); +// (*((float *) fpreg)) = tmp; + pCppArgs[nPos] = fpreg; + pUnoArgs[nPos] = fpreg; + nf++; + fpreg += 2; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 1; + } + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (ng < 4) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng += 2; + gpreg += 2; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw += 2; + } + break; + + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (ng < 5) { + pCppArgs[nPos] = (((char *)gpreg) + 3); + pUnoArgs[nPos] = (((char *)gpreg) + 3); + ng++; + gpreg++; + } else { + pCppArgs[nPos] = (((char *)ovrflw) + 3); + pUnoArgs[nPos] = (((char *)ovrflw) + 3); + ovrflw++; + } + break; + + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (ng < 5) { + pCppArgs[nPos] = (((char *)gpreg)+ 2); + pUnoArgs[nPos] = (((char *)gpreg)+ 2); + ng++; + gpreg++; + } else { + pCppArgs[nPos] = (((char *)ovrflw) + 2); + pUnoArgs[nPos] = (((char *)ovrflw) + 2); + ovrflw++; + } + break; + + + default: + if (ng < 5) { + pCppArgs[nPos] = gpreg; + pUnoArgs[nPos] = gpreg; + ng++; + gpreg++; + } else { + pCppArgs[nPos] = ovrflw; + pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + + if (ng < 5) { + pCppArgs[nPos] = *(void **)gpreg; + pCppStack = gpreg; + ng++; + gpreg++; + } else { + pCppArgs[nPos] = *(void **)ovrflw; + pCppStack = ovrflw; + ovrflw++; + } + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//============================================================================ +static typelib_TypeClass cpp_mediate( + sal_uInt32 nOffsetAndIndex, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + sal_Int16 nVtableOffset = (nOffsetAndIndex >> 16); + sal_Int16 nFunctionIndex = (nOffsetAndIndex & 0xFFFF); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // _this_ ptr is patched cppu_XInterfaceProxy object + void * pThis; + if( nFunctionIndex & 0x8000 ) + { + nFunctionIndex &= 0x7fff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void privateSnippetExecutor( sal_uInt32 nOffsetAndIndex, void** gpregptr, void** fpregptr, void** ovrflw) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "privateSnippetExecutor\n"); +#endif + + + sal_Int32 gpreg[8]; + double fpreg[8]; + + memcpy( gpreg, gpregptr, 32); + memcpy( fpreg, fpregptr, 64); + + volatile long nRegReturn[2]; + + typelib_TypeClass aType = + cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, ovrflw, + (sal_Int64*)nRegReturn ); + + switch( aType ) + { + + // move return value into register space + // (will be loaded by machine code snippet) + + case typelib_TypeClass_BOOLEAN: + { + unsigned long tmp = (unsigned long)(*(unsigned char *)nRegReturn); + __asm__ volatile ( "l 2,%0\n\t" : : + "m"(tmp) : "2" ); + break; + } + case typelib_TypeClass_BYTE: + { + long tmp = (long)(*(signed char *)nRegReturn); + __asm__ volatile ( "l 2,%0\n\t" : : + "m"(tmp) : "2" ); + break; + } + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + { + unsigned long tmp = (unsigned long)(*(unsigned short *)nRegReturn); + __asm__ volatile ( "l 2,%0\n\t" : : + "m"(tmp) : "2" ); + break; + } + case typelib_TypeClass_SHORT: + { + long tmp = (long)(*(short *)nRegReturn); + __asm__ volatile ( "l 2,%0\n\t" : : + "m"(tmp) : "2" ); + break; + } + case typelib_TypeClass_FLOAT: + __asm__ volatile ( "le 0,%0\n\t" : : + "m" (*((float*)nRegReturn)) : "16" ); + break; + + case typelib_TypeClass_DOUBLE: + __asm__ volatile ( "ld 0,%0\n\t" : : + "m" (*((double*)nRegReturn)) : "16" ); + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__ volatile ( "lm 2,3,%0\n\t" : : + "m"(nRegReturn[0]) : "2", "3" ); + break; + + default: + __asm__ volatile ( "l 2,%0\n\t" : : + "m"(nRegReturn[0]) : "2" ); + break; + } +} + +const int codeSnippetSize = 50; + +unsigned char* codeSnippet( unsigned char * code, sal_Int16 nFunctionIndex, sal_Int16 nVtableOffset, bool simple_ret_type ) +{ + sal_uInt32 nOffsetAndIndex = ( ( nVtableOffset ) << 16 ) | ( nFunctionIndex ); + + if (! simple_ret_type) + nOffsetAndIndex |= 0x8000; + + OSL_ASSERT( sizeof (long) == 4 ); + + /* generate this code */ + // lr %r0,%r13 + // bras %r13,0x6 + // .long privateSnippetExecutor + // .long nOffsetAndIndex + // stm %r2,%r6,8(%r15) + // std %f0,64(%r15) + // std %f2,72(%r15) + + // l %r2,4(%r13) + // la %r3,8(%r15) + // la %r4,64(%r15) + // la %r5,96(%r15) + // l %r1,0(%r13) + // lr %r13,%r0 + // br %r1 + + unsigned char * p = code; + *reinterpret_cast< sal_Int16 * >(p) = 0x180d; + p += sizeof(sal_Int16); + *reinterpret_cast< sal_Int32 * >(p) = 0xa7d50006; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = + reinterpret_cast< sal_Int32 >(privateSnippetExecutor); + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = nOffsetAndIndex; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x9026f008; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x6000f040; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x6020f048; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x5820d004; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x4130f008; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x4140f040; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x4150f060; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int32 * >(p) = 0x5810d000; + p += sizeof(sal_Int32); + *reinterpret_cast< sal_Int16 * >(p) = 0x18d0; + p += sizeof(sal_Int16); + *reinterpret_cast< sal_Int16 * >(p) = 0x07f1; + p += sizeof(sal_Int16); + + return (code + codeSnippetSize); +} +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, unsigned char const *) +{ +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/except.cxx b/bridges/source/cpp_uno/gcc3_linux_s390/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_s390/makefile.mk new file mode 100644 index 000000000000..bda85f359210 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)$(CPUNAME)" == "GCCLINUX3gcc3S390" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/share.hxx b/bridges/source/cpp_uno/gcc3_linux_s390/share.hxx new file mode 100644 index 000000000000..4ec09c29ff0a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/share.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_s390/uno2cpp.cxx new file mode 100644 index 000000000000..2680ff460e71 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/uno2cpp.cxx @@ -0,0 +1,636 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ +static sal_Int32 +invoke_count_words(char * pPT) +{ + sal_Int32 overflow = 0, gpr = 0, fpr = 0; + int c; // character of parameter type being decoded + + while (*pPT != 'X') { + c = *pPT; + switch (c) { + case 'D': /* type is double */ + if (fpr < 2) fpr++; else overflow+=2; + break; + + case 'F': /* type is float */ + if (fpr < 2) fpr++; else overflow++; + break; + + case 'H': /* type is long long */ + if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; + break; + + case 'S': + case 'T': + case 'B': + case 'C': + if (gpr < 5) gpr++; else overflow++; + break; + + default: + if (gpr < 5) gpr++; else overflow++; + break; + } + pPT++; + } + /* Round up number of overflow words to ensure stack + stays aligned to 8 bytes. */ + return (overflow + 1) & ~1; +} + +static void +//invoke_copy_to_stack(sal_Int32 paramCount, sal_Int32 * pStackLongs, char * pPT, sal_Int32* d_ov, sal_Int32 overflow) +invoke_copy_to_stack(sal_Int32 * pStackLongs, char * pPT, sal_Int32* d_ov, sal_Int32 overflow) +{ + sal_Int32 *d_gpr = d_ov + overflow; + sal_Int64 *d_fpr = (sal_Int64 *)(d_gpr + 5); + sal_Int32 gpr = 0, fpr = 0; + char c; + + while (*pPT != 'X') { + c = *pPT; + switch (c) { + case 'D': /* type is double */ + if (fpr < 2) + *((double*) d_fpr) = *((double *)pStackLongs), d_fpr++, fpr++; + else + *((double*) d_ov ) = *((double *)pStackLongs), d_ov+=2; + + pStackLongs += 2; + break; + + case 'F': /* type is float */ + if (fpr < 2) { + *((sal_Int64*) d_fpr) = 0; + *((float*) d_fpr) = *((float *)pStackLongs), d_fpr++, fpr++; + } + else { + *((sal_Int64*) d_ov) = 0; + *((float*) d_ov ) = *((float *)pStackLongs), d_ov++; + } + + pStackLongs += 1; + break; + + case 'H': /* type is long long */ + if (gpr < 4) { + *((sal_Int64*) d_gpr) = *((sal_Int64*) pStackLongs), d_gpr+=2, gpr+=2; + } + else { + *((sal_Int64*) d_ov ) = *((sal_Int64*) pStackLongs), d_ov+=2, gpr=5; + } + pStackLongs += 2; + break; + + case 'S': + if (gpr < 5) + *((sal_uInt32*)d_gpr) = *((unsigned short*)pStackLongs), d_gpr++, gpr++; + else + *((sal_uInt32*)d_ov ) = *((unsigned short*)pStackLongs), d_ov++; + pStackLongs += 1; + break; + + case 'T': + if (gpr < 5) + *((sal_Int32*)d_gpr) = *((signed short*)pStackLongs), d_gpr++, gpr++; + else + *((sal_Int32*)d_ov ) = *((signed short*)pStackLongs), d_ov++; + pStackLongs += 1; + break; + + case 'B': + if (gpr < 5) + *((sal_uInt32*)d_gpr) = *((unsigned char*)pStackLongs), d_gpr++, gpr++; + else + *((sal_uInt32*)d_ov ) = *((unsigned char*)pStackLongs), d_ov++; + pStackLongs += 1; + break; + + case 'C': + if (gpr < 5) + *((sal_Int32*)d_gpr) = *((signed char*)pStackLongs), d_gpr++, gpr++; + else + *((sal_Int32*)d_ov ) = *((signed char*)pStackLongs), d_ov++; + pStackLongs += 1; + break; + + default: + if (gpr < 5) + *((sal_Int32*)d_gpr) = *pStackLongs, d_gpr++, gpr++; + else + *((sal_Int32*)d_ov ) = *pStackLongs, d_ov++; + pStackLongs += 1; + break; + } + pPT++; + } +} + +//================================================================================================== +static void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + char * pPT, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs) +{ + + // parameter list is mixed list of * and values + // reference parameters are pointers + + // the basic idea here is to use gpr[5] as a storage area for + // the future values of registers r2 to r6 needed for the call, + // and similarly fpr[2] as a storage area for the future values + // of floating point registers f0 to f2 + + sal_Int32 *vtable = *(sal_Int32 **)pThis; +// sal_Int32 method = vtable[nVtableIndex + 2]; + sal_Int32 method = vtable[nVtableIndex]; + sal_Int32 overflow = invoke_count_words (pPT); + sal_Int32 result; + volatile double dret; // temporary function return values + volatile float fret; + volatile int iret, iret2; + + void * dummy = alloca(32); // dummy alloca to force r11 usage for exception handling + + __asm__ __volatile__ + ( + "lr 7,15\n\t" + "ahi 7,-48\n\t" + + "lr 3,%2\n\t" + "sll 3,2\n\t" + "lcr 3,3\n\t" + "l 2,0(15)\n\t" + "la 15,0(3,7)\n\t" + "st 2,0(15)\n\t" + + "lr 2,%0\n\t" + "lr 3,%1\n\t" + "la 4,96(15)\n\t" + "lr 5,%2\n\t" + "basr 14,%3\n\t" + + "ld 0,116(7)\n\t" + "ld 2,124(7)\n\t" + "lm 2,6,96(7)\n\t" + : + : "r" (pStackLongs), + "r" (pPT), + "r" (overflow), + "a" (invoke_copy_to_stack), + "a" (method), + "X" (dummy) + : "2", "3", "4", "5", "6", "7", "memory" + ); +// "basr 14,%8\n\t" + + (*(void (*)())method)(); + + __asm__ __volatile__ + ( + "la 15,48(7)\n\t" + + "lr %2,2\n\t" + "lr %3,3\n\t" + "ler %0,0\n\t" + "ldr %1,0\n\t" + + : "=f" (fret), "=f" (dret), "=r" (iret), "=r" (iret2) + ); + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: +// ((long*)pRegisterReturn)[0] = iret; + ((long*)pRegisterReturn)[1] = iret2; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = iret; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)iret; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)iret; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = fret; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + } +} + + +//============================================================================ +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // need to know parameter types for callVirtualMethod so generate a signature string + char * pParamType = (char *) alloca(nParams+2); + char * pPT = pParamType; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + *pPT++ = 'I'; //signify that a complex return type on stack + pCppStack += sizeof(void *); + } + } + // push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + *pPT++ = 'I'; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + + // we need to know type of each param so that we know whether to use + // gpr or fpr to pass in parameters: + // Key: I - int, long, pointer, etc means pass in gpr + // B - byte value passed in gpr + // S - short value passed in gpr + // F - float value pass in fpr + // D - double value pass in fpr + // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc + // X - indicates end of parameter description string + + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pPT++ = 'I'; + break; + case typelib_TypeClass_SHORT: + *pPT++ = 'T'; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + *pPT++ = 'S'; + break; + case typelib_TypeClass_BOOLEAN: + *pPT++ = 'B'; + break; + case typelib_TypeClass_BYTE: + *pPT++ = 'C'; + break; + case typelib_TypeClass_FLOAT: + *pPT++ = 'F'; + break; + case typelib_TypeClass_DOUBLE: + *pPT++ = 'D'; + pCppStack += sizeof(sal_Int32); // extra long + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pPT++ = 'H'; + pCppStack += sizeof(sal_Int32); // extra long + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // KBH: FIXME: is this the right way to pass these + *pPT++='I'; + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // terminate the signature string + *pPT++='X'; + *pPT=0; + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "unoInterfaceProxyDispatch\n"); +#endif + + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx new file mode 100644 index 000000000000..fa3bd5fb687a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx @@ -0,0 +1,658 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include <stdio.h> + +using namespace ::com::sun::star::uno; + +namespace +{ +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "as far as cpp2uno_call\n"); +#endif + int ng = 0; //number of gpr registers used + int nf = 0; //number of fpr regsiters used + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)gpreg; + gpreg++; + ng++; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + gpreg++; + ng++; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "simple\n"); +#endif + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + if (nf < s390x::MAX_SSE_REGS) + { + if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT) + { + float tmp = (float) (*((double *)fpreg)); + (*((float *) fpreg)) = tmp; + } + + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++; + nf++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + case typelib_TypeClass_BYTE: + case typelib_TypeClass_BOOLEAN: + if (ng < s390x::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-1)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-1)); + ovrflw++; + } + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (ng < s390x::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-2)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-2)); + ovrflw++; + } + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (ng < s390x::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-4)); + ng++; + gpreg++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-4)); + ovrflw++; + } + break; + default: + if (ng < s390x::MAX_GPR_REGS) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; + ovrflw++; + } + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "complex, ng is %d\n", ng); +#endif + + void *pCppStack; //temporary stack pointer + + if (ng < s390x::MAX_GPR_REGS) + { + pCppArgs[nPos] = pCppStack = *gpreg++; + ng++; + } + else + { + pCppArgs[nPos] = pCppStack = *ovrflw; + ovrflw++; + } + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of params\n"); +#endif + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//============================================================================ +static typelib_TypeClass cpp_mediate( + sal_uInt64 nOffsetAndIndex, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" ); + + sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32); + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); + +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "nVTableOffset, nFunctionIndex are %x %x\n", nVtableOffset, nFunctionIndex); +#endif + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= cpp_mediate () =\nGPR's (%d): ", 5 ); + for ( unsigned int i = 0; i < 5; ++i ) + fprintf( stderr, "0x%lx, ", gpreg[i] ); + fprintf( stderr, "\n"); + fprintf( stderr, "\nFPR's (%d): ", 4 ); + for ( unsigned int i = 0; i < 4; ++i ) + fprintf( stderr, "0x%lx (%f), ", fpreg[i], fpreg[i] ); + fprintf( stderr, "\n"); + } +#endif + + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + + // _this_ ptr is patched cppu_XInterfaceProxy object + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +long privateSnippetExecutor(long r2, long r3, long r4, long r5, long r6, long firstonstack) +{ + register long r0 asm("r0"); + sal_uInt64 nOffsetAndIndex = r0; + + long sp = (long)&firstonstack; + + sal_uInt64 gpreg[s390x::MAX_GPR_REGS]; + gpreg[0] = r2; + gpreg[1] = r3; + gpreg[2] = r4; + gpreg[3] = r5; + gpreg[4] = r6; + + double fpreg[s390x::MAX_SSE_REGS]; + register double f0 asm("f0"); fpreg[0] = f0; + register double f2 asm("f2"); fpreg[1] = f2; + register double f4 asm("f4"); fpreg[2] = f4; + register double f6 asm("f6"); fpreg[3] = f6; + + volatile long nRegReturn[1]; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "before mediate with %lx\n",nOffsetAndIndex); + fprintf(stderr, "doubles are %f %f %f %f\n", fpreg[0], fpreg[1], fpreg[2], fpreg[3]); +#endif + typelib_TypeClass aType = + cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, (void**)sp, + (sal_Int64*)nRegReturn ); +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "after mediate ret is %lx %ld\n", nRegReturn[0], nRegReturn[0]); +#endif + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + nRegReturn[0] = (unsigned long)(*(unsigned char *)nRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + nRegReturn[0] = (unsigned long)(*(unsigned short *)nRegReturn); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + nRegReturn[0] = (unsigned long)(*(unsigned int *)nRegReturn); + break; + case typelib_TypeClass_VOID: + default: + break; + case typelib_TypeClass_FLOAT: + { + double tmp = (double) (*((float *)nRegReturn)); + (*((double *) nRegReturn)) = tmp; + } + //deliberate fall through + case typelib_TypeClass_DOUBLE: + __asm__ ( "ld 0,%0\n\t" + : : "m" (*((double*)nRegReturn)) ); + break; + } + return nRegReturn[0]; +} + +const int codeSnippetSize = 32; + +unsigned char *codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool simple_ret_type ) +{ + sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_Int64) nFunctionIndex ); + + if (! simple_ret_type) + nOffsetAndIndex |= 0x80000000; + + unsigned char * p = code; + *(short *)&p[0] = 0x0d10; /* basr %r1,0 */ + *(short *)&p[2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ + *(short *)&p[4] = 0x100e; + *(short *)&p[6] = 0x0004; + *(short *)&p[8] = 0x07f1; /* br %r1 */ + *(long *)&p[16] = (long)nOffsetAndIndex; + *(long *)&p[24] = (long)&privateSnippetExecutor; + return (code + codeSnippetSize); +} +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, unsigned char const *) +{ +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); +#endif + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/except.cxx b/bridges/source/cpp_uno/gcc3_linux_s390x/except.cxx new file mode 100644 index 000000000000..ea4188bac998 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/except.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_s390x/makefile.mk new file mode 100644 index 000000000000..9539dd6edf9b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)$(CPUNAME)" == "GCCLINUX3gcc3S390X" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/share.hxx b/bridges/source/cpp_uno/gcc3_linux_s390x/share.hxx new file mode 100644 index 000000000000..69176377606b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/share.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +namespace s390x +{ + enum s390xlimits { MAX_GPR_REGS = 5, MAX_SSE_REGS = 4 }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_s390x/uno2cpp.cxx new file mode 100644 index 000000000000..379d086ce85a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/uno2cpp.cxx @@ -0,0 +1,539 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <stdio.h> +#include <string.h> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +void MapReturn(long r2, double f0, typelib_TypeClass eTypeClass, sal_uInt64* pRegisterReturn) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr,"Mapping Return with %lx %ld %f\n", r2, r2, f0); +#endif + switch (eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pRegisterReturn = r2; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *(unsigned int*)pRegisterReturn = (unsigned int)r2; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)r2; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)r2; + break; + case typelib_TypeClass_FLOAT: + *reinterpret_cast<float *>( pRegisterReturn ) = f0; + break; + case typelib_TypeClass_DOUBLE: + *reinterpret_cast<double *>( pRegisterReturn ) = f0; + break; + default: + break; + } +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "end of MapReturn with %x\n", pRegisterReturn ? *pRegisterReturn : 0); +#endif +} + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ + { \ + if ( nr < s390x::MAX_SSE_REGS ) \ + { \ + pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \ + } \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + } + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ + if ( nr < s390x::MAX_SSE_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ + if ( nr < s390x::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ + if ( nr < s390x::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ + if ( nr < s390x::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ + if ( nr < s390x::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +namespace +{ +//================================================================================================== +void callVirtualMethod( + void * pThis, sal_Int32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ + // Should not happen, but... + if ( nFPR > s390x::MAX_SSE_REGS ) + nFPR = s390x::MAX_SSE_REGS; + if ( nGPR > s390x::MAX_GPR_REGS ) + nGPR = s390x::MAX_GPR_REGS; + +#if OSL_DEBUG_LEVEL > 2 + // Let's figure out what is really going on here + { + fprintf( stderr, "= nStack is %d\n", nStack ); + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( unsigned int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( unsigned int i = 0; i < nFPR; ++i ) + fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn); + } +#endif + + // Load parameters to stack, if necessary + // Stack, if used, must be 8-bytes aligned + sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 ); + memcpy( stack, pStack, nStack * 8 ); + + // To get pointer to method + // a) get the address of the vtable + sal_uInt64 pMethod = *((sal_uInt64 *)pThis); + // b) get the address from the vtable entry at offset + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); + FunctionCall pFunc = (FunctionCall)pMethod; + + switch (nFPR) //deliberate fall through + { + case 4: + asm volatile("ld 6,%0" :: "m"(pFPR[3]) : "16"); + case 3: + asm volatile("ld 4,%0" :: "m"(pFPR[2]) : "16"); + case 2: + asm volatile("ld 2,%0" :: "m"(pFPR[1]) : "16"); + case 1: + asm volatile("ld 0,%0" :: "m"(pFPR[0]) : "16"); + default: + break; + } + + volatile long r2; + volatile double f0; + + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4]); + + __asm__ __volatile__ ( + "lgr %0,2\n\t" + "ldr %1,0\n\t" + : "=r" (r2), "=f" (f0) + : : + ); + + MapReturn(r2, f0, pReturnTypeDescr->eTypeClass, (sal_uInt64*)pRegisterReturn); +} + + +//============================================================================ +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; + + sal_uInt64 pGPR[s390x::MAX_GPR_REGS]; + sal_uInt32 nGPR = 0; + + double pFPR[s390x::MAX_SSE_REGS]; + sal_uInt32 nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack ); + } + } + // push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; + + INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack ); + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack ); + } + } + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, + pStackStart, (pStack - pStackStart), + pGPR, nGPR, + pFPR, nFPR ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if OSL_DEBUG_LEVEL > 2 + fprintf(stderr, "unoInterfaceProxyDispatch\n"); +#endif + + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/call.s b/bridges/source/cpp_uno/gcc3_linux_sparc/call.s new file mode 100644 index 000000000000..09c611237968 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/call.s @@ -0,0 +1,10 @@ +.global doFlushCode +doFlushCode: +.L: flush %o0 + deccc %o1 + bne .L + add %o0, 8, %o0 + retl + nop +.size doFlushCode,(.-doFlushCode) +.align 8 diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx new file mode 100644 index 000000000000..54833796f337 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/data.h> +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" +#include "share.hxx" + +using namespace com::sun::star::uno; + +namespace +{ +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: [ret ptr], this, params + char * pCppStack = (char *)pCallStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void**)pCppStack; + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + pCppStack += sizeof( void* ); + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { + pCppArgs[nPos] = pUnoArgs[nPos] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr); + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + { + if ((reinterpret_cast< long >(pCppStack) & 7) != 0) + { + OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) ); + void * pDest = alloca( sizeof (sal_Int64) ); + *reinterpret_cast< sal_Int32 * >(pDest) = + *reinterpret_cast< sal_Int32 const * >(pCppStack); + *(reinterpret_cast< sal_Int32 * >(pDest) + 1) = + *(reinterpret_cast< sal_Int32 const * >(pCppStack) + 1); + pCppArgs[nPos] = pUnoArgs[nPos] = pDest; + } + pCppStack += sizeof (sal_Int32); // extra long + break; + default: + break; + } + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: this, params + // eventual [ret*] lies at pCallStack -1 + // so count down pCallStack by one to keep it simple + // pCallStack: this, params + // eventual [ret*] lies at pCallStack -1 + // so count down pCallStack by one to keep it simple + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + static_cast< char * >(*pCallStack) - nVtableOffset); + if ((nFunctionIndex & 0x80000000) != 0) { + nFunctionIndex &= 0x7FFFFFFF; + --pCallStack; + } + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), (XInterface *)pCppI ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); +#endif + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + return eRet; +} + + + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call() +{ + sal_Int64 nRegReturn; + int nFunctionIndex; + void** pCallStack; + int vTableOffset; + +void * pRegReturn = &nRegReturn; + + __asm__( "st %%i0, %0\n\t" + "st %%i1, %1\n\t" + "st %%i2, %2\n\t" + : : "m"(nFunctionIndex), "m"(pCallStack), "m"(vTableOffset) ); + +// fprintf(stderr,"cpp_mediate nFunctionIndex=%x\n",nFunctionIndex); +// fflush(stderr); + + sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, vTableOffset, pCallStack+17, (sal_Int64*)&nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "ld %0, %%l0\n\t" + "ldsb [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "ld %0, %%l0\n\t" + "ldsh [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%i0\n\t" + "add %%l0, 4, %%l0\n\t" + "ld [%%l0], %%i1\n\t" + : : "m"(pRegReturn) ); + + break; + case typelib_TypeClass_FLOAT: + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%f0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_DOUBLE: + __asm__( "ld %0, %%l0\n\t" + "ldd [%%l0], %%f0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_VOID: + break; + default: + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + } + + if( bComplex ) + { + __asm__( "add %i7, 4, %i7\n\t" ); + // after call to complex return valued funcion there is an unimp instruction + } + +} +//__________________________________________________________________________________________________ + +int const codeSnippetSize = 56; +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) +{ + sal_uInt32 index = functionIndex; + if (!simpleRetType) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + OSL_ASSERT(sizeof (unsigned int) == 4); + // st %o0, [%sp+68]: + *p++ = 0xD023A044; + // st %o1, [%sp+72]: + *p++ = 0xD223A048; + // st %o2, [%sp+76]: + *p++ = 0xD423A04C; + // st %o3, [%sp+80]: + *p++ = 0xD623A050; + // st %o4, [%sp+84]: + *p++ = 0xD823A054; + // st %o5, [%sp+88]: + *p++ = 0xDA23A058; + // sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // sethi %hi(vtableOffset), %o2: + *p++ = 0x15000000 | (vtableOffset >> 10); + // or %o2, %lo(vtableOffset), %o2: + *p++ = 0x9412A000 | (vtableOffset & 0x3FF); + // sethi %hi(cpp_vtable_call), %o3: + *p++ = 0x17000000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) >> 10); + // or %o3, %lo(cpp_vtable_call), %o3: + *p++ = 0x9612E000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) & 0x3FF); + // jmpl %o3, %g0: + *p++ = 0x81C2C000; + // mov %sp, %o1: + *p++ = 0x9210000E; + OSL_ASSERT( + reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} //end of namespace + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; //null + slots[-1].fn = 0; //destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vTableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vTableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vTableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vTableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +// use flush code from cc50_solaris_sparc + +extern "C" void doFlushCode(unsigned long address, unsigned long count); + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * begin, unsigned char const * end) +{ + unsigned long n = end - begin; + if (n != 0) { + unsigned long adr = reinterpret_cast< unsigned long >(begin); + unsigned long off = adr & 7; + doFlushCode(adr - off, (n + off + 7) >> 3); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/except.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc/except.cxx new file mode 100644 index 000000000000..f95848008920 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/except.cxx @@ -0,0 +1,330 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if defined BRIDGES_DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if defined BRIDGES_DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iiFind( m_generatedRttis.find( unoName ) ); + if (iiFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if defined BRIDGES_DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iiFind->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if defined BRIDGES_DEBUG + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if defined BRIDGES_DEBUG + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_sparc/makefile.mk new file mode 100644 index 000000000000..3940038247c3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/makefile.mk @@ -0,0 +1,85 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)" == "GCCLINUXS" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# # work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +CFLAGSNOOPT=-O0 + +NOOPTFILES = \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/call.obj + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + + +SHL1TARGET=$(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS= $(SLOFILES) +SHL1LIBS =$(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(ASM) $(AFLAGS) -o $(SLO)$/$(@:b).o $< && touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/share.hxx b/bridges/source/cpp_uno/gcc3_linux_sparc/share.hxx new file mode 100644 index 000000000000..3526f19082cd --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/share.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "uno/mapping.h" +#include <typeinfo> +#include <exception> +#include <cstddef> +namespace CPPU_CURRENT_NAMESPACE +{ +void dummy_can_throw_anything( char const * ); +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); + +inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType ) +{ + switch( pType->nSize ) + { + case 1: return pIn + 3; + case 2: return pIn + 2; + case 3: return pIn + 1; + // Huh ? perhaps a char[3] ? Though that would be a pointer + // well, we have it anyway for symmetry + } + return pIn; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc/uno2cpp.cxx new file mode 100644 index 000000000000..f99e60d0d6fd --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/uno2cpp.cxx @@ -0,0 +1,606 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <malloc.h> +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +using namespace com::sun::star::uno; + +using ::rtl::OUString; +using ::rtl::OString; +using ::rtl::OUStringToOString; + +namespace +{ +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 /* nVtableIndex */, + void * pRegisterReturn, + typelib_TypeClass eReturnType, +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs) +#else + sal_Int32 * /*pStackLongs*/, + sal_Int32 /*nStackLongs*/) +#endif +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && + (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long o0 = 0, o1 = 0; // for register returns + volatile double f0d = 0; + volatile float f0f = 0; + volatile long long saveReg[7]; + + __asm__ ( + // save registers + "std %%l0, [%4]\n\t" + "mov %4, %%l0\n\t" + "mov %%l0, %%l1\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o0, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l6, [%%l0]\n\t" + "mov %%l1, %%l7\n\t" + + // increase our own stackframe if necessary + "mov %%sp, %%l3\n\t" // save stack ptr for readjustment + + "subcc %%i5, 7, %%l0\n\t" + "ble .LmoveOn\n\t" + "nop\n\t" + + "sll %%l0, 2, %%l0\n\t" + "add %%l0, 96, %%l0\n\t" + "mov %%sp, %%l1\n\t" // old stack ptr + "sub %%sp, %%l0, %%l0\n\t" // future stack ptr + "andcc %%l0, 7, %%g0\n\t" // align stack to 8 + "be .LisAligned\n\t" + "nop\n\t" + "sub %%l0, 4, %%l0\n" + ".LisAligned:\n\t" + "mov %%l0, %%o5\n\t" // save newly computed stack ptr + "add %%g0, 16, %%o4\n" + + // now copy longs down to save register window + // and local variables + ".LcopyDown:\n\t" + "ld [%%l1], %%l2\n\t" + "st %%l2,[%%l0]\n\t" + "add %%l0, 4, %%l0\n\t" + "add %%l1, 4, %%l1\n\t" + "subcc %%o4, 1, %%o4\n\t" + "bne .LcopyDown\n\t" + + "mov %%o5, %%sp\n\t" // move new stack ptr (hopefully) atomically + // while register window is valid in both spaces + // (scheduling might hit in copyDown loop) + + "sub %%i5, 7, %%l0\n\t" // copy parameters past the sixth to stack + "add %%i4, 28, %%l1\n\t" + "add %%sp, 92, %%l2\n" + ".LcopyLong:\n\t" + "ld [%%l1], %%o0\n\t" + "st %%o0, [%%l2]\n\t" + "add %%l1, 4, %%l1\n\t" + "add %%l2, 4, %%l2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "bne .LcopyLong\n\t" + "nop\n" + + ".LmoveOn:\n\t" + "mov %%i5, %%l0\n\t" // prepare out registers + "mov %%i4, %%l1\n\t" + + "ld [%%l1], %%o0\n\t" // prepare complex return ptr + "st %%o0, [%%sp+64]\n\t" + "sub %%l0, 1, %%l0\n\t" + "add %%l1, 4, %%l1\n\t" + + "ld [%%l1], %%o0\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o1\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o3\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o4\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o5\n" + + ".LdoCall:\n\t" + "ld [%%i0], %%l0\n\t" // get vtable ptr + +"sll %%i1, 2, %%l6\n\t" +// "add %%l6, 8, %%l6\n\t" + "add %%l6, %%l0, %%l0\n\t" +// // vtable has 8byte wide entries, +// // upper half contains 2 half words, of which the first +// // is the this ptr patch ! +// // first entry is (or __tf) + +// "ldsh [%%l0], %%l6\n\t" // load this ptr patch +// "add %%l6, %%o0, %%o0\n\t" // patch this ptr + +// "add %%l0, 4, %%l0\n\t" // get virtual function ptr + "ld [%%l0], %%l0\n\t" + + "ld [%%i4], %%l2\n\t" + "subcc %%l2, %%g0, %%l2\n\t" + "bne .LcomplexCall\n\t" + "nop\n\t" + "call %%l0\n\t" + "nop\n\t" + "ba .LcallReturned\n\t" + "nop\n" + ".LcomplexCall:\n\t" + "call %%l0\n\t" + "nop\n\t" + "unimp\n" + + ".LcallReturned:\n\t" + "mov %%l3, %%sp\n\t" // readjust stack so that our locals are where they belong + "st %%o0, %0\n\t" // save possible return registers into our locals + "st %%o1, %1\n\t" + "std %%f0, %2\n\t" + "st %%f0, %3\n\t" + + // restore registers + "ldd [%%l7], %%l0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l6\n\t" + : : + "m"(o0), + "m"(o1), + "m"(f0d), + "m"(f0f), + "r"(&saveReg[0]) + ); + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = o1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = o0; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)o0; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)o0; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = f0f; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = f0d; + break; + default: + break; + } +} + +//================================================================================================= +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: complex ret ptr, this, values|ptr ... + char * pCppStack = + (char *)alloca( (nParams+2) * sizeof(sal_Int64) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + *(void**)pCppStack = NULL; + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + } + pCppStack += sizeof(void*); + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) ); + *reinterpret_cast< sal_Int32 * >(pCppStack) = + *reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ]); + pCppStack += sizeof (sal_Int32); + *reinterpret_cast< sal_Int32 * >(pCppStack) = + *(reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ] ) + 1); + break; + default: + uno_copyAndConvertData( + pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic" ); + + if( nStackLongs & 1 ) + // stack has to be 8 byte aligned + nStackLongs++; + callVirtualMethod( + pAdjustedThisPtr, + aVtableSlot.index, + pCppReturn, + pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, + nStackLongs); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch( ... ) + { + // get exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() ); +#endif + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +// typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx new file mode 100644 index 000000000000..938cbf5ded06 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx @@ -0,0 +1,340 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +// This is an implementation of the x86-64 ABI as described in 'System V +// Application Binary Interface, AMD64 Architecture Processor Supplement' +// (http://www.x86-64.org/documentation/abi-0.95.pdf) +// +// The code in this file is a modification of src/x86/ffi64.c from libffi +// (http://sources.redhat.com/libffi/) which is under the following license: + +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de> + + x86-64 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <abi.hxx> + +#include <rtl/ustring.hxx> + +using namespace x86_64; + +/* Register class used for passing given 64bit part of the argument. + These represent classes as documented by the PS ABI, with the exception + of SSESF, SSEDF classes, that are basically SSE class, just gcc will + use SF or DFmode move instead of DImode to avoid reformating penalties. + + Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves + whenever possible (upper half does contain padding). + */ +enum x86_64_reg_class +{ + X86_64_NO_CLASS, + X86_64_INTEGER_CLASS, + X86_64_INTEGERSI_CLASS, + X86_64_SSE_CLASS, + X86_64_SSESF_CLASS, + X86_64_SSEDF_CLASS, + X86_64_SSEUP_CLASS, + X86_64_X87_CLASS, + X86_64_X87UP_CLASS, + X86_64_MEMORY_CLASS +}; + +#define MAX_CLASSES 4 + +/* x86-64 register passing implementation. See x86-64 ABI for details. Goal + of this code is to classify each 8bytes of incoming argument by the register + class and assign registers accordingly. */ + +/* Return the union class of CLASS1 and CLASS2. + See the x86-64 PS ABI for details. */ + +static enum x86_64_reg_class +merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) +{ + /* Rule #1: If both classes are equal, this is the resulting class. */ + if (class1 == class2) + return class1; + + /* Rule #2: If one of the classes is NO_CLASS, the resulting class is + the other class. */ + if (class1 == X86_64_NO_CLASS) + return class2; + if (class2 == X86_64_NO_CLASS) + return class1; + + /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ + if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) + return X86_64_MEMORY_CLASS; + + /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ + if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) + || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) + return X86_64_INTEGERSI_CLASS; + if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS + || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) + return X86_64_INTEGER_CLASS; + + /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */ + if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS + || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS) + return X86_64_MEMORY_CLASS; + + /* Rule #6: Otherwise class SSE is used. */ + return X86_64_SSE_CLASS; +} + +/* Classify the argument of type TYPE and mode MODE. + CLASSES will be filled by the register class used to pass each word + of the operand. The number of words is returned. In case the parameter + should be passed in memory, 0 is returned. As a special case for zero + sized containers, classes[0] will be NO_CLASS and 1 is returned. + + See the x86-64 PS ABI for details. +*/ +static int +classify_argument( typelib_TypeDescriptionReference *pTypeRef, enum x86_64_reg_class classes[], int byteOffset ) +{ + switch ( pTypeRef->eTypeClass ) + { + case typelib_TypeClass_VOID: + classes[0] = X86_64_NO_CLASS; + return 1; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_ENUM: + if ( ( byteOffset % 8 + pTypeRef->pType->nSize ) <= 4 ) + classes[0] = X86_64_INTEGERSI_CLASS; + else + classes[0] = X86_64_INTEGER_CLASS; + return 1; + case typelib_TypeClass_FLOAT: + if ( ( byteOffset % 8 ) == 0 ) + classes[0] = X86_64_SSESF_CLASS; + else + classes[0] = X86_64_SSE_CLASS; + return 1; + case typelib_TypeClass_DOUBLE: + classes[0] = X86_64_SSEDF_CLASS; + return 1; + /*case LONGDOUBLE: + classes[0] = X86_64_X87_CLASS; + classes[1] = X86_64_X87UP_CLASS; + return 2;*/ + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_TYPEDEF: + case typelib_TypeClass_UNION: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_ARRAY: + case typelib_TypeClass_INTERFACE: + return 0; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + const int UNITS_PER_WORD = 8; + int words = ( pTypeDescr->nSize + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD; + enum x86_64_reg_class subclasses[MAX_CLASSES]; + + /* If the struct is larger than 16 bytes, pass it on the stack. */ + if ( pTypeDescr->nSize > 16 ) + { + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return 0; + } + + for ( int i = 0; i < words; i++ ) + classes[i] = X86_64_NO_CLASS; + + const typelib_CompoundTypeDescription *pStruct = reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr ); + + /* Merge the fields of structure. */ + for ( sal_Int32 nMember = 0; nMember < pStruct->nMembers; ++nMember ) + { + typelib_TypeDescriptionReference *pTypeInStruct = pStruct->ppTypeRefs[ nMember ]; + int offset = byteOffset + pStruct->pMemberOffsets[ nMember ]; + + int num = classify_argument( pTypeInStruct, subclasses, offset ); + + if ( num == 0 ) + { + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return 0; + } + + for ( int i = 0; i < num; i++ ) + { + int pos = offset / 8; + classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] ); + } + } + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + + /* Final merger cleanup. */ + for ( int i = 0; i < words; i++ ) + { + /* If one class is MEMORY, everything should be passed in + memory. */ + if ( classes[i] == X86_64_MEMORY_CLASS ) + return 0; + + /* The X86_64_SSEUP_CLASS should be always preceded by + X86_64_SSE_CLASS. */ + if ( classes[i] == X86_64_SSEUP_CLASS + && ( i == 0 || classes[i - 1] != X86_64_SSE_CLASS ) ) + classes[i] = X86_64_SSE_CLASS; + + /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ + if ( classes[i] == X86_64_X87UP_CLASS + && ( i == 0 || classes[i - 1] != X86_64_X87_CLASS ) ) + classes[i] = X86_64_SSE_CLASS; + } + return words; + } + + default: +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "Unhandled case: pType->eTypeClass == %d\n", pTypeRef->eTypeClass ); +#endif + OSL_ASSERT(0); + } + return 0; /* Never reached. */ +} + +/* Examine the argument and return set number of register required in each + class. Return 0 iff parameter should be passed in memory. */ +bool x86_64::examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE ) +{ + enum x86_64_reg_class classes[MAX_CLASSES]; + int n; + + n = classify_argument( pTypeRef, classes, 0 ); + + if ( n == 0 ) + return false; + + nUsedGPR = 0; + nUsedSSE = 0; + for ( n--; n >= 0; n-- ) + switch ( classes[n] ) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + nUsedGPR++; + break; + case X86_64_SSE_CLASS: + case X86_64_SSESF_CLASS: + case X86_64_SSEDF_CLASS: + nUsedSSE++; + break; + case X86_64_NO_CLASS: + case X86_64_SSEUP_CLASS: + break; + case X86_64_X87_CLASS: + case X86_64_X87UP_CLASS: + if ( !bInReturn ) + return false; + break; + default: +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "Unhandled case: classes[n] == %d\n", classes[n] ); +#endif + OSL_ASSERT(0); + } + return true; +} + +bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) +{ + int g, s; + + return examine_argument( pTypeRef, true, g, s ) == 0; +} + +void x86_64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64 *pGPR, const double *pSSE, void *pStruct ) +{ + enum x86_64_reg_class classes[MAX_CLASSES]; + int n; + + n = classify_argument( pTypeRef, classes, 0 ); + + sal_uInt64 *pStructAlign = reinterpret_cast<sal_uInt64 *>( pStruct ); + for ( n--; n >= 0; n-- ) + switch ( classes[n] ) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + *pStructAlign++ = *pGPR++; + break; + case X86_64_SSE_CLASS: + case X86_64_SSESF_CLASS: + case X86_64_SSEDF_CLASS: + *pStructAlign++ = *reinterpret_cast<const sal_uInt64 *>( pSSE++ ); + break; + default: + break; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.hxx new file mode 100644 index 000000000000..c9f71f18078b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BRIDGES_CPP_UNO_X86_64_ABI_HXX_ +#define _BRIDGES_CPP_UNO_X86_64_ABI_HXX_ + +// This is an implementation of the x86-64 ABI as described in 'System V +// Application Binary Interface, AMD64 Architecture Processor Supplement' +// (http://www.x86-64.org/documentation/abi-0.95.pdf) + +#include <typelib/typedescription.hxx> + +namespace x86_64 +{ + +/* 6 general purpose registers are used for parameter passing */ +const sal_uInt32 MAX_GPR_REGS = 6; + +/* 8 SSE registers are used for parameter passing */ +const sal_uInt32 MAX_SSE_REGS = 8; + +/* Count number of required registers. + + Examine the argument and return set number of register required in each + class. + + Return false iff parameter should be passed in memory. +*/ +bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE ); + +/** Does function that returns this type use a hidden parameter, or registers? + + The value can be returned either in a hidden 1st parameter (which is a + pointer to a structure allocated by the caller), or in registers (rax, rdx + for the integers, xmm0, xmm1 for the floating point numbers). +*/ +bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); + +void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* pGPR, const double* pSSE, void *pStruct ); + +} // namespace x86_64 + +#endif // _BRIDGES_CPP_UNO_X86_64_ABI_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s b/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s new file mode 100644 index 000000000000..a0572ef61641 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s @@ -0,0 +1,96 @@ + .text + .align 2 +.globl privateSnippetExecutor + .type privateSnippetExecutor, @function +privateSnippetExecutor: +.LFB3: + pushq %rbp +.LCFI0: + movq %rsp, %rbp +.LCFI1: + subq $160, %rsp +.LCFI2: + movq %r10, -152(%rbp) # Save (nVtableOffset << 32) + nFunctionIndex + + movq %rdi, -112(%rbp) # Save GP registers + movq %rsi, -104(%rbp) + movq %rdx, -96(%rbp) + movq %rcx, -88(%rbp) + movq %r8 , -80(%rbp) + movq %r9 , -72(%rbp) + + movsd %xmm0, -64(%rbp) # Save FP registers + movsd %xmm1, -56(%rbp) + movsd %xmm2, -48(%rbp) + movsd %xmm3, -40(%rbp) + movsd %xmm4, -32(%rbp) + movsd %xmm5, -24(%rbp) + movsd %xmm6, -16(%rbp) + movsd %xmm7, -8(%rbp) + + leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn + leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw + leaq -64(%rbp), %rcx # 4th param: void ** fpreg + leaq -112(%rbp), %rdx # 3rd param: void ** gpreg + movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset + movl -152(%rbp), %edi # 1st param: sal_int32 nFunctionIndex + + call cpp_vtable_call + + cmp $10, %rax # typelib_TypeClass_FLOAT + je .Lfloat + cmp $11, %rax # typelib_TypeClass_DOUBLE + je .Lfloat + + movq -144(%rbp), %rax # Return value (int case) + movq -136(%rbp), %rdx # Return value (int case) + movq -144(%rbp), %xmm0 # Return value (int case) + movq -136(%rbp), %xmm1 # Return value (int case) + jmp .Lfinish +.Lfloat: + movlpd -144(%rbp), %xmm0 # Return value (float/double case) + +.Lfinish: + leave + ret +.LFE3: + .size privateSnippetExecutor, .-privateSnippetExecutor + .section .eh_frame,"a",@progbits +.Lframe1: + .long .LECIE1-.LSCIE1 +.LSCIE1: + .long 0x0 + .byte 0x1 + .string "zR" + .uleb128 0x1 + .sleb128 -8 + .byte 0x10 + .uleb128 0x1 + .byte 0x1b + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 + .uleb128 0x1 + .align 8 +.LECIE1: +.LSFDE1: + .long .LEFDE1-.LASFDE1 +.LASFDE1: + .long .LASFDE1-.Lframe1 + .long .LFB3-. + .long .LFE3-.LFB3 + .uleb128 0x0 + .byte 0x4 + .long .LCFI0-.LFB3 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI1-.LCFI0 + .byte 0xd + .uleb128 0x6 + .align 8 +.LEFDE1: + .section .note.GNU-stack,"",@progbits diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx new file mode 100644 index 000000000000..264e1e96fbac --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx @@ -0,0 +1,529 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <stdlib.h> +#include <boost/unordered_map.hpp> + +#include <rtl/alloc.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "abi.hxx" +#include "share.hxx" + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +//================================================================================================== + +// Perform the UNO call +// +// We must convert the paramaters stored in gpreg, fpreg and ovrflw to UNO +// arguments and call pThis->getUnoI()->pDispatcher. +// +// gpreg: [ret *], this, [gpr params] +// fpreg: [fpr params] +// ovrflw: [gpr or fpr params (properly aligned)] +// +// [ret *] is present when we are returning a structure bigger than 16 bytes +// Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp). +// Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary. +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_uInt64 * pRegisterReturn /* space for register return */ ) +{ + unsigned int nr_gpr = 0; //number of gpr registers used + unsigned int nr_fpr = 0; //number of fpr registers used + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if ( pReturnTypeDescr ) + { + if ( x86_64::return_in_hidden_param( pReturnTypeRef ) ) + { + pCppReturn = *gpreg++; + nr_gpr++; + + pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn ); // direct way + } + else + pUnoReturn = pRegisterReturn; // direct way for simple types + } + + // pop this + gpreg++; + nr_gpr++; + + // stack space + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + + int nUsedGPR = 0; + int nUsedSSE = 0; +#if OSL_DEBUG_LEVEL > 0 + bool bFitsRegisters = +#endif + x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE ); + if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value + { + // Simple types must fit exactly one register on x86_64 + OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) ); + + if ( nUsedSSE == 1 ) + { + if ( nr_fpr < x86_64::MAX_SSE_REGS ) + { + pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++; + nr_fpr++; + } + else + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++; + } + else if ( nUsedGPR == 1 ) + { + if ( nr_gpr < x86_64::MAX_GPR_REGS ) + { + pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++; + nr_gpr++; + } + else + pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++; + } + } + else // struct <= 16 bytes || ptr to complex value || ref + { + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + void *pCppStack; + if ( nr_gpr < x86_64::MAX_GPR_REGS ) + { + pCppArgs[nPos] = pCppStack = *gpreg++; + nr_gpr++; + } + else + pCppArgs[nPos] = pCppStack = *ovrflw++; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if ( pUnoExc ) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if ( pParams[nIndex].bOut ) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if ( pCppReturn ) // has complex return + { + if ( pUnoReturn != pCppReturn ) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if ( pReturnTypeDescr ) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +extern "C" typelib_TypeClass cpp_vtable_call( + sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_uInt64 * pRegisterReturn /* space for register return */ ) +{ + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (properly aligned)] + void * pThis; + if ( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + pThis = static_cast<char *>( pThis ) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis ); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" ); + if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex ) + { + throw RuntimeException( OUString(RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!")), + reinterpret_cast<XInterface *>( pCppI ) ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch ( aMemberDescr.get()->eTypeClass ) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_TypeDescriptionReference *pAttrTypeRef = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef; + + if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex ) + { + // is GET method + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = pAttrTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch ( nFunctionIndex ) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() ); + if ( pTD ) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface) + ( pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, + pCppI->getOid().pData, + reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) ); + + if ( pInterface ) + { + ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + + reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + { + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() ); + + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), + pMethodTD->pReturnTypeRef, + pMethodTD->nParams, + pMethodTD->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + } + break; + } + default: + { + throw RuntimeException( OUString(RTL_CONSTASCII_USTRINGPARAM("no member description found!")), + reinterpret_cast<XInterface *>( pCppI ) ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +extern "C" void privateSnippetExecutor( ... ); + +const int codeSnippetSize = 24; + +// Generate a trampoline that redirects method calls to +// privateSnippetExecutor(). +// +// privateSnippetExecutor() saves all the registers that are used for +// parameter passing on x86_64, and calls the cpp_vtable_call(). +// When it returns, privateSnippetExecutor() sets the return value. +// +// Note: The code snippet we build here must not create a stack frame, +// otherwise the UNO exceptions stop working thanks to non-existing +// unwinding info. +unsigned char * codeSnippet( unsigned char * code, + sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + bool bHasHiddenParam ) SAL_THROW( () ) +{ + sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex ); + + if ( bHasHiddenParam ) + nOffsetAndIndex |= 0x80000000; + + // movq $<nOffsetAndIndex>, %r10 + *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49; + *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex; + + // movq $<address of the privateSnippetExecutor>, %r11 + *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49; + *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor ); + + // jmpq *%r11 + *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49; + +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, + "==> codeSnippet, functionIndex=%d%s, vtableOffset=%d\n", + nFunctionIndex), (bHasHiddenParam ? "|0x80000000":""), nVtableOffset); +#endif + + return code + codeSnippetSize; +} + +//================================================================================================== +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +//================================================================================================== +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +//================================================================================================== +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +//================================================================================================== + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset, + sal_Int32 functionCount, sal_Int32 nVtableOffset ) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos ) + { + typelib_TypeDescription * pTD = 0; + + TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] ); + OSL_ASSERT( pTD ); + + if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass ) + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); + + // get method + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( code, nFunctionOffset++, nVtableOffset, + x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) ); + + if ( ! pAttrTD->bReadOnly ) + { + // set method + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false ); + } + } + else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass ) + { + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); + + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( code, nFunctionOffset++, nVtableOffset, + x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) ); + } + else + OSL_ASSERT( false ); + + TYPELIB_DANGER_RELEASE( pTD ); + } + return code; +} + +//================================================================================================== +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const * ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/except.cxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/except.cxx new file mode 100644 index 000000000000..e841bc0c37e5 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/except.cxx @@ -0,0 +1,340 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) +#if defined(FREEBSD) && __FreeBSD_version < 702104 + : m_hApp( dlopen( 0, RTLD_NOW | RTLD_GLOBAL ) ) +#else + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +#endif +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); +#if defined(FREEBSD) && __FreeBSD_version < 702104 /* #i22253# */ + rtti = (type_info *)dlsym( RTLD_DEFAULT, symName.getStr() ); +#else + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); +#endif + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) ); + if (iFind2 == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind2->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_x86-64/makefile.mk new file mode 100644 index 000000000000..f8b6d8e17b82 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/makefile.mk @@ -0,0 +1,90 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCLINUXXgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCOPENBSDXgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCFREEBSDXgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCNETBSDXgcc3" || \ + "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCDRAGONFLYXgcc3" \ + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer -fno-strict-aliasing + +# In case the compiler supports AVX this code segfaults so specifically turn +# it off. +.IF "$(HAVE_GCC_AVX)" == "TRUE" + CFLAGSCXX+= -mno-avx +.ENDIF + +SLOFILES= \ + $(SLO)$/abi.obj \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(CC) -c -o $(SLO)$/$(@:b).o $< + touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx new file mode 100644 index 000000000000..da2367ad172b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx new file mode 100644 index 000000000000..c830f877ccf2 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx @@ -0,0 +1,608 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <exception> +#include <typeinfo> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "rtl/alloc.h" +#include "rtl/ustrbuf.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include <bridges/cpp_uno/shared/bridge.hxx> +#include <bridges/cpp_uno/shared/types.hxx> +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "abi.hxx" +#include "share.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +//================================================================================================== +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) __attribute__((noinline)); + +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, + void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn, + sal_uInt64 *pStack, sal_uInt32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ +#if OSL_DEBUG_LEVEL > 1 + // Let's figure out what is really going on here + { + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( unsigned int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( unsigned int i = 0; i < nFPR; ++i ) + fprintf( stderr, "%f, ", pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + } +#endif + + // The call instruction within the asm section of callVirtualMethod may throw + // exceptions. So that the compiler handles this correctly, it is important + // that (a) callVirtualMethod might call dummy_can_throw_anything (although this + // never happens at runtime), which in turn can throw exceptions, and (b) + // callVirtualMethod is not inlined at its call site (so that any exceptions are + // caught which are thrown from the instruction calling callVirtualMethod): + if ( !pThis ) + CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something + + // Should not happen, but... + if ( nFPR > x86_64::MAX_SSE_REGS ) + nFPR = x86_64::MAX_SSE_REGS; + if ( nGPR > x86_64::MAX_GPR_REGS ) + nGPR = x86_64::MAX_GPR_REGS; + + // Get pointer to method + sal_uInt64 pMethod = *((sal_uInt64 *)pThis); + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + // Load parameters to stack, if necessary + if ( nStack ) + { + // 16-bytes aligned + sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16; + sal_uInt64 *pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes ); + memcpy( pCallStack, pStack, nStackBytes ); + } + + // Return values + sal_uInt64 rax; + sal_uInt64 rdx; + double xmm0; + double xmm1; + + asm volatile ( + + // Fill the xmm registers + "movq %2, %%rax\n\t" + + "movsd (%%rax), %%xmm0\n\t" + "movsd 8(%%rax), %%xmm1\n\t" + "movsd 16(%%rax), %%xmm2\n\t" + "movsd 24(%%rax), %%xmm3\n\t" + "movsd 32(%%rax), %%xmm4\n\t" + "movsd 40(%%rax), %%xmm5\n\t" + "movsd 48(%%rax), %%xmm6\n\t" + "movsd 56(%%rax), %%xmm7\n\t" + + // Fill the general purpose registers + "movq %1, %%rax\n\t" + + "movq (%%rax), %%rdi\n\t" + "movq 8(%%rax), %%rsi\n\t" + "movq 16(%%rax), %%rdx\n\t" + "movq 24(%%rax), %%rcx\n\t" + "movq 32(%%rax), %%r8\n\t" + "movq 40(%%rax), %%r9\n\t" + + // Perform the call + "movq %0, %%r11\n\t" + "movq %3, %%rax\n\t" + "call *%%r11\n\t" + + // Fill the return values + "movq %%rax, %4\n\t" + "movq %%rdx, %5\n\t" + "movsd %%xmm0, %6\n\t" + "movsd %%xmm1, %7\n\t" + : + : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ), + "m" ( rax ), "m" ( rdx ), "m" ( xmm0 ), "m" ( xmm1 ) + : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11" + ); + + switch (pReturnTypeRef->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax ); + break; + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + *reinterpret_cast<double *>( pRegisterReturn ) = xmm0; + break; + default: + { + sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize; + if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0) + { + sal_uInt64 longs[2]; + longs[0] = rax; + longs[1] = rdx; + + double doubles[2]; + doubles[0] = xmm0; + doubles[1] = xmm1; + x86_64::fill_struct( pReturnTypeRef, &longs[0], &doubles[0], pRegisterReturn); + } + break; + } + } +} + +//================================================================================================== + +// Macros for easier insertion of values to registers or stack +// pSV - pointer to the source +// nr - order of the value [will be increased if stored to register] +// pFPR, pGPR - pointer to the registers +// pDS - pointer to the stack [will be increased if stored here] + +// The value in %xmm register is already prepared to be retrieved as a float, +// thus we treat float and double the same +#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \ + if ( nr < x86_64::MAX_SSE_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! + +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ + if ( nr < x86_64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ + if ( nr < x86_64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ + if ( nr < x86_64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ + if ( nr < x86_64::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +//================================================================================================== + +namespace { + +void appendCString(OUStringBuffer & buffer, char const * text) { + if (text != 0) { + buffer.append( + OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1)); + // use 8859-1 to avoid conversion failure + } +} + +} + +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // Maxium space for [complex ret ptr], values | ptr ... + // (but will be used less - some of the values will be in pGPR and pFPR) + sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ); + sal_uInt64 *pStackStart = pStack; + + sal_uInt64 pGPR[x86_64::MAX_GPR_REGS]; + sal_uInt32 nGPR = 0; + + double pFPR[x86_64::MAX_SSE_REGS]; + sal_uInt32 nFPR = 0; + + // Return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below) + + bool bSimpleReturn = true; + if ( pReturnTypeDescr ) + { + if ( x86_64::return_in_hidden_param( pReturnTypeRef ) ) + bSimpleReturn = false; + + if ( bSimpleReturn ) + pCppReturn = pUnoReturn; // direct way for simple types + else + { + // complex return via ptr + pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )? + __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn; + INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack ); + } + } + + // Push "this" pointer + void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; + INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack ); + + // Args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // Indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // Type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack ); + break; + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack ); + } + } + + try + { + try { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeRef, bSimpleReturn, + pStackStart, ( pStack - pStackStart ), + pGPR, nGPR, + pFPR, nFPR ); + } catch (Exception &) { + throw; + } catch (std::exception & e) { + OUStringBuffer buf; + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw ")); + appendCString(buf, typeid(e).name()); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": ")); + appendCString(buf, e.what()); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >()); + } catch (...) { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "C++ code threw unknown exception")), + Reference< XInterface >()); + } + + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +//================================================================================================== + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, // get, then set method + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/call.s b/bridges/source/cpp_uno/gcc3_macosx_intel/call.s new file mode 100644 index 000000000000..814af56f4c34 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/call.s @@ -0,0 +1,327 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + .text + +.align 1, 0x90 +.globl _privateSnippetExecutorGeneral +_privateSnippetExecutorGeneral: +LFBg: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIg0: + movl %esp,%ebp +LCFIg1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 32bit returnValue + leave + ret +LFEg: + .long .-_privateSnippetExecutorGeneral + +.align 1, 0x90 +.globl _privateSnippetExecutorVoid +_privateSnippetExecutorVoid: +LFBv: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIv0: + movl %esp,%ebp +LCFIv1: + sub $8,%esp # padding + pushl $0 # 32bit null pointer (returnValue not used) + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + leave + ret +LFEv: + .long .-_privateSnippetExecutorVoid + +.align 1, 0x90 +.globl _privateSnippetExecutorHyper +_privateSnippetExecutorHyper: +LFBh: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIh0: + movl %esp,%ebp +LCFIh1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 64bit returnValue, lower half + movl 20(%esp),%edx # 64bit returnValue, upper half + leave + ret +LFEh: + .long .-_privateSnippetExecutorHyper + +.align 1, 0x90 +.globl _privateSnippetExecutorFloat +_privateSnippetExecutorFloat: +LFBf: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIf0: + movl %esp,%ebp +LCFIf1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + flds 16(%esp) # 32bit returnValue + leave + ret +LFEf: + .long .-_privateSnippetExecutorFloat + +.align 1, 0x90 +.globl _privateSnippetExecutorDouble +_privateSnippetExecutorDouble: +LFBd: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFId0: + movl %esp,%ebp +LCFId1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + fldl 16(%esp) # 64bit returnValue + leave + ret +LFEd: + .long .-_privateSnippetExecutorDouble + +.align 1, 0x90 +.globl _privateSnippetExecutorClass +_privateSnippetExecutorClass: +LFBc: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +LCFIc0: + movl %esp,%ebp +LCFIc1: + subl $0x8,%esp # padding + 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call L_cpp_vtable_call$stub + movl 16(%esp),%eax # 32bit returnValue + leave + ret $4 +LFEc: + .long .-_privateSnippetExecutorClass + + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame1: + .set L$set$frame1,LECIE1-LSCIE1 + .long L$set$frame1 # length +LSCIE1: + .long 0 # CIE_ID + .byte 1 # version + .ascii "zPR\0" # augmentation + .byte 1 # code_alignment_factor (.uleb128 1) + .byte 0x7c # data_alignment_factor (.sleb128 -4) + .byte 8 # return_address_register + .byte 0x6 # augmentation size 7: + .byte 0x9b # ??? + .long L___gxx_personality_v0$non_lazy_ptr-. + .byte 0x10 + # initial_instructions: + .byte 0x0C # DW_CFA_def_cfa %esp, 4 + .byte 5 + .byte 4 + .byte 0x88 # DW_CFA_offset ret, 1 + .byte 1 + .align 2 +LECIE1: + .globl _privateSnippetExecutorGeneral.eh +_privateSnippetExecutorGeneral.eh: +LSFDEg: + .set L$set$g1,LEFDEg-LASFDEg + .long L$set$g1 # length +LASFDEg: + .long LASFDEg-EH_frame1 # CIE_pointer + .long LFBg-. # initial_location + .long LFEg-LFBg # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIg0-LFBg + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIg1-LCFIg0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEg: + .globl _privateSnippetExecutorVoid.eh +_privateSnippetExecutorVoid.eh: +LSFDEv: + .set L$set$v1,LEFDEv-LASFDEv + .long L$set$v1 # length +LASFDEv: + .long LASFDEv-EH_frame1 # CIE_pointer + .long LFBv-. # initial_location + .long LFEv-LFBv # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIv0-LFBv + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIv1-LCFIv0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEv: + .globl _privateSnippetExecutorHyper.eh +_privateSnippetExecutorHyper.eh: +LSFDEh: + .set L$set$h1,LEFDEh-LASFDEh + .long L$set$h1 # length +LASFDEh: + .long LASFDEh-EH_frame1 # CIE_pointer + .long LFBh-. # initial_location + .long LFEh-LFBh # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIh0-LFBh + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIh1-LCFIh0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEh: + .globl _privateSnippetExecutorFloat.eh +_privateSnippetExecutorFloat.eh: +LSFDEf: + .set L$set$f1,LEFDEf-LASFDEf + .long L$set$f1 # length +LASFDEf: + .long LASFDEf-EH_frame1 # CIE_pointer + .long LFBf-. # initial_location + .long LFEf-LFBf # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIf0-LFBf + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIf1-LCFIf0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEf: + .globl _privateSnippetExecutorDouble.eh +_privateSnippetExecutorDouble.eh: +LSFDEd: + .set L$set$d1,LEFDEd-LASFDEd + .long L$set$d1 # length +LASFDEd: + .long LASFDEd-EH_frame1 # CIE_pointer + .long LFBd-. # initial_location + .long LFEd-LFBd # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFId0-LFBd + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFId1-LCFId0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEd: + .globl _privateSnippetExecutorClass.eh +_privateSnippetExecutorClass.eh: +LSFDEc: + .set L$set$c1,LEFDEc-LASFDEc + .long L$set$c1 # length +LASFDEc: + .long LASFDEc-EH_frame1 # CIE_pointer + .long LFBc-. # initial_location + .long LFEc-LFBc # address_range + .byte 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIc0-LFBc + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .byte 8 + .byte 0x84 # DW_CFA_offset %ebp, 2 + .byte 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long LCFIc1-LCFIc0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .byte 4 + .align 2 +LEFDEc: + .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 +L_cpp_vtable_call$stub: + .indirect_symbol _cpp_vtable_call + hlt ; hlt ; hlt ; hlt ; hlt + .section __IMPORT,__pointers,non_lazy_symbol_pointers +L___gxx_personality_v0$non_lazy_ptr: + .indirect_symbol ___gxx_personality_v0 + .long 0 + .constructor + .destructor + .align 1 + .subsections_via_symbols diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_macosx_intel/cpp2uno.cxx new file mode 100644 index 000000000000..64f27baf9a93 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/cpp2uno.cxx @@ -0,0 +1,534 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +#include "boost/static_assert.hpp" +#include <stdio.h> + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +void cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + void * pReturnValue ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + // xxx todo: test PolyStructy<STRUCT<long>> foo() + if (CPPU_CURRENT_NAMESPACE::isSimpleReturnType( pReturnTypeDescr )) + { + pUnoReturn = pReturnValue; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + if (pReturnValue != pCppReturn) { + // complex return ptr is set to eax if return value + // is not transferred via eax[/edx]: + *static_cast< void ** >(pReturnValue) = pCppReturn; + } + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } +} + + +//================================================================================================== +extern "C" void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack, + void * pReturnValue ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "%p %p %p pThis=%p, pCppI=%p, function index=%d, vtable offset=%d\n", pCallStack[0], pCallStack[1], pCallStack[2], pThis, pCppI, nFunctionIndex, nVtableOffset ); +#endif + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "name=%s\n", rtl::OUStringToOString(pTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_UTF8).getStr() ); +#endif + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "calling %s\n", rtl::OUStringToOString(aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_UTF8).getStr()); +#endif + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pReturnValue ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pReturnValue ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *static_cast< void ** >(pReturnValue) = pCallStack[1]; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pReturnValue ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + } + } +} + +//================================================================================================== +extern "C" void privateSnippetExecutorGeneral(); +extern "C" void privateSnippetExecutorVoid(); +extern "C" void privateSnippetExecutorHyper(); +extern "C" void privateSnippetExecutorFloat(); +extern "C" void privateSnippetExecutorDouble(); +extern "C" void privateSnippetExecutorClass(); +extern "C" typedef void (*PrivateSnippetExecutor)(); + +int const codeSnippetSize = 16; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + typelib_TypeDescriptionReference * pReturnTypeRef) +{ + PrivateSnippetExecutor exec; + if (pReturnTypeRef == 0) { + exec = privateSnippetExecutorVoid; + } + else { + switch (pReturnTypeRef->eTypeClass) { + case typelib_TypeClass_VOID: + exec = privateSnippetExecutorVoid; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + exec = privateSnippetExecutorHyper; + break; + case typelib_TypeClass_FLOAT: + exec = privateSnippetExecutorFloat; + break; + case typelib_TypeClass_DOUBLE: + exec = privateSnippetExecutorDouble; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + bool const bSimpleReturnStruct = + CPPU_CURRENT_NAMESPACE::isSimpleReturnType(pReturnTypeDescr); + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + if (bSimpleReturnStruct && nRetSize <= 8) { + exec = privateSnippetExecutorGeneral; // fills eax + if (nRetSize > 4) + exec = privateSnippetExecutorHyper; // fills eax/edx + break; + } + } + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_ANY: + functionIndex |= 0x80000000; + exec = privateSnippetExecutorClass; + break; + default: + exec = privateSnippetExecutorGeneral; + break; + } + } + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov function_index, %eax: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov vtable_offset, %edx: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // jmp privateSnippetExecutor: + *p++ = 0xE9; + *reinterpret_cast< sal_Int32 * >(p) + = ((unsigned char *) exec) - p - sizeof (sal_Int32); + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, + "==> codeSnippet to %s, functionIndex=%d%s, vtableOffset=%d\n", + (exec == privateSnippetExecutorGeneral ? "General" : + (exec == privateSnippetExecutorVoid ? "Void" : + (exec == privateSnippetExecutorHyper ? "Hyper" : + (exec == privateSnippetExecutorFloat ? "Float" : + (exec == privateSnippetExecutorDouble ? "Double" : + (exec == privateSnippetExecutorClass ? "Class" : + "???")))))), + (functionIndex & ~0x80000000), (functionIndex & 0x80000000) ? "|0x80000000":"", vtableOffset); +#endif + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + 0 /* indicates VOID */); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/except.cxx b/bridges/source/cpp_uno/gcc3_macosx_intel/except.cxx new file mode 100644 index 000000000000..a14bc8b9aec0 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/except.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) ); + if (iFind2 == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind2->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_macosx_intel/makefile.mk new file mode 100644 index 000000000000..7bca40bbaf97 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCMACOSXIgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib +SHL1RPATH = URELIB + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(CC) -c -o $(SLO)$/$(@:b).o $< + touch $@ diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/share.hxx b/bridges/source/cpp_uno/gcc3_macosx_intel/share.hxx new file mode 100644 index 000000000000..8b105c0880b3 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/share.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false); + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_macosx_intel/uno2cpp.cxx new file mode 100644 index 000000000000..9f0000587923 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/uno2cpp.cxx @@ -0,0 +1,496 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + // stack padding to keep stack aligned: + "shl $2, %%eax\n\t" + "neg %%eax\n\t" + "add %%esp, %%eax\n\t" + "and $0xf, %%eax\n\t" + "sub %%eax, %%esp\n\t" + // copy: + "mov %%edx, %%eax\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + switch( pReturnTypeDescr->eTypeClass ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + default: { + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 8 && nRetSize > 0) { + if (nRetSize > 4) + static_cast<long *>(pRegisterReturn)[1] = edx; + static_cast<long *>(pRegisterReturn)[0] = eax; + } + break; + } + } +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + bool bSimpleReturn = true; + + if (pReturnTypeDescr) + { + bSimpleReturn = CPPU_CURRENT_NAMESPACE::isSimpleReturnType( + pReturnTypeDescr); + if (bSimpleReturn) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + // complex return via ptr + *(void **)pCppStack = pCppReturn; + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, bSimpleReturn, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "caught C++ exception\n" ); +#endif + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace CPPU_CURRENT_NAMESPACE { +bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive) +{ + if (bridges::cpp_uno::shared::isSimpleType( pTD )) + return true; + // Only structs of exactly 1, 2, 4, or 8 bytes are returned through + // registers, see <http://developer.apple.com/documentation/DeveloperTools/ + // Conceptual/LowLevelABI/Articles/IA32.html>: + if (pTD->eTypeClass == typelib_TypeClass_STRUCT && + (recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8)) + { + typelib_CompoundTypeDescription *const pCompTD = + (typelib_CompoundTypeDescription *) pTD; + for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) { + typelib_TypeDescription * pMemberTD = 0; + TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] ); + bool const b = isSimpleReturnType(pMemberTD, true); + TYPELIB_DANGER_RELEASE( pMemberTD ); + if (! b) + return false; + } + return true; + } + return false; +} +} + +//================================================================================================== + +namespace bridges { namespace cpp_uno { namespace shared { +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx new file mode 100644 index 000000000000..232144c5e80d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx @@ -0,0 +1,732 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + + // gpreg: [ret *], this, [gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (space for entire parameter list in structure format properly aligned)] + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + sal_Int32 ngpreg = 0; + sal_Int32 nfpreg = 0; + + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via ptr (pCppReturn) + { + pCppReturn = *gpreg; + ngpreg++; + ++ovrflw; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + ngpreg++; + ++ovrflw; + + // after handling optional return pointer and "this" + // make use of the space that is allocated to store all parameters in the callers stack + // by comying the proper registers filled with parameters to that space + char * pCppStack = (char *)ovrflw; + + + sal_Int32 nPos; + + for ( nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + if (rParam.bOut) + { + if (ngpreg < 8) + { + *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; + } + pCppStack += sizeof (sal_Int32); + } + else + { + switch (rParam.pTypeRef->eTypeClass) + { + case typelib_TypeClass_FLOAT: + if (nfpreg < 13) + { + *(float *)pCppStack = ((double *)fpreg)[nfpreg++]; + } + pCppStack += sizeof (float); + ngpreg += 1; + break; + case typelib_TypeClass_DOUBLE: + if (nfpreg < 13) + { + *(double *)pCppStack = ((double *)fpreg)[nfpreg++]; + } + pCppStack += sizeof (double); + ngpreg += 2; + break; + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_HYPER: + if (ngpreg < 8) + { + *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; + } + pCppStack += sizeof (sal_Int32); + // fall through on purpose + default: + if (ngpreg < 8) + { + *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; + } + pCppStack += sizeof (sal_Int32); + } + } + } + + // now the stack has all of the paramters stored in it ready to be processed + // so we are ready to build the uno call stack + pCppStack = (char *)ovrflw; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pCppArgs[nPos] = pCppStack +3; + pUnoArgs[nPos] = pCppStack +3; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pCppArgs[nPos] = pCppStack +2; + pUnoArgs[nPos] = pCppStack +2; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + pCppStack += sizeof(sal_Int32); // extra long (two regs) + break; + default: + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to return reg + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** gpreg, void ** fpreg, void ** ovrflw, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // gpreg: [ret *], this, [other gpr params] + // fpreg: [fpr params] + // ovrflw: [gpr or fpr params (in space allocated for all params properly aligned)] + + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = gpreg[1]; + } + else + { + pThis = gpreg[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); + + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( gpreg[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = gpreg[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + gpreg, fpreg, ovrflw, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) +{ + sal_Int32 gpreg[8]; + double fpreg[13]; + + // FIXME: why are we restoring the volatile ctr register here + sal_Int32 ctrsave = ((sal_Int32*)gpregptr)[-1]; + + memcpy( gpreg, gpregptr, 32); + memcpy( fpreg, fpregptr, 104); + + volatile long nRegReturn[2]; + + // sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; + + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn ); + + // FIXME: why are we restoring the volatile ctr register here + // FIXME: and why are we putting back the values for r4, r5, and r6 as well + // FIXME: this makes no sense to me, all of these registers are volatile! + __asm__( "lwz r4, %0\n\t" + "mtctr r4\n\t" + "lwz r4, %1\n\t" + "lwz r5, %2\n\t" + "lwz r6, %3\n\t" + : : "m"(ctrsave), "m"(gpreg[1]), "m"(gpreg[2]), "m"(gpreg[3]) ); + + switch( aType ) + { + + // move return value into register space + // (will be loaded by machine code snippet) + + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "lbz r3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "lhz r3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + + case typelib_TypeClass_FLOAT: + __asm__( "lfs f1,%0\n\t" : : + "m" (*((float*)nRegReturn)) ); + break; + + case typelib_TypeClass_DOUBLE: + __asm__( "lfd f1,%0\n\t" : : + "m" (*((double*)nRegReturn)) ); + break; + + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "lwz r4,%0\n\t" : : + "m"(nRegReturn[1]) ); // fall through + + default: + __asm__( "lwz r3,%0\n\t" : : + "m"(nRegReturn[0]) ); + break; + } +} + + +int const codeSnippetSize = 136; + +unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, + sal_Int32 vtableOffset, bool simpleRetType ) +{ + if (! simpleRetType ) + functionIndex |= 0x80000000; + + // OSL_ASSERT( sizeof (long) == 4 ); + + // FIXME: why are we leaving an 8k gap in the stack here + // FIXME: is this to allow room for signal handling frames? + // FIXME: seems like overkill here but this is what was done for Mac OSX for gcc2 + // FIXME: also why no saving of the non-volatile CR pieces here, to be safe + // FIXME: we probably should + + /* generate this code */ + + // # so first save gpr 3 to gpr 10 (aligned to 4) + // stw r3, -8000(r1) + // stw r4, -7996(r1) + // stw r5, -7992(r1) + // stw r6, -7988(r1) + // stw r7, -7984(r1) + // stw r8, -7980(r1) + // stw r9, -7976(r1) + // stw r10,-7972(r1) + + // # next save fpr 1 to fpr 13 (aligned to 8) + // stfd f1, -7968(r1) + // stfd f2, -7960(r1) + // stfd f3, -7952(r1) + // stfd f4, -7944(r1) + // stfd f5, -7936(r1) + // stfd f6, -7928(r1) + // stfd f7, -7920(r1) + // stfd f8, -7912(r1) + // stfd f9, -7904(r1) + // stfd f10,-7896(r1) + // stfd f11,-7888(r1) + // stfd f12,-7880(r1) + // stfd f13,-7872(r1) + + // FIXME: ctr is volatile, while are we saving it and not CR? + // mfctr r3 + // stw r3, -8004(r1) + + // # now here is where cpp_vtable_call must go + // lis r3,0xdead + // ori r3,r3,0xbeef + // mtctr r3 + + // # now load up the functionIndex number + // lis r3, 0xdead + // ori r3,r3,0xbeef + + // # now load up the vtableOffset + // lis r4, 0xdead + // ori r4,r4,0xbeef + + // #now load up the pointer to the saved gpr registers + // addi r5,r1,-8000 + + // #now load up the pointer to the saved fpr registers + // addi r6,r1,-7968 + + // #now load up the pointer to the overflow call stack + // addi r7,r1,24 # frame pointer plus 24 + + // bctr + + unsigned long * p = (unsigned long *) code; + + * p++ = 0x9061e0c0; + * p++ = 0x9081e0c4; + * p++ = 0x90a1e0c8; + * p++ = 0x90c1e0cc; + * p++ = 0x90e1e0d0; + * p++ = 0x9101e0d4; + * p++ = 0x9121e0d8; + * p++ = 0x9141e0dc; + * p++ = 0xd821e0e0; + * p++ = 0xd841e0e8; + * p++ = 0xd861e0f0; + * p++ = 0xd881e0f8; + * p++ = 0xd8a1e100; + * p++ = 0xd8c1e108; + * p++ = 0xd8e1e110; + * p++ = 0xd901e118; + * p++ = 0xd921e120; + * p++ = 0xd941e128; + * p++ = 0xd961e130; + * p++ = 0xd981e138; + * p++ = 0xd9a1e140; + * p++ = 0x7c6902a6; + * p++ = 0x9061e0bc; + * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16); + * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); + * p++ = 0x7c6903a6; + * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16); + * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF); + * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16); + * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF); + * p++ = 0x38a1e0c0; + * p++ = 0x38c1e0e0; + * p++ = 0x38e10018; + * p++ = 0x4e800420; + + return (code + codeSnippetSize); + +} + + +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) +{ + int const lineSize = 32; + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("sync" : : : "memory"); + for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { + __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); + } + __asm__ volatile ("isync" : : : "memory"); +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + + // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); + // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); + // fflush(stderr); + + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_powerpc/except.cxx b/bridges/source/cpp_uno/gcc3_macosx_powerpc/except.cxx new file mode 100644 index 000000000000..274f99987cb8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/except.cxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#ifdef DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#ifdef DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iiFind( m_generatedRttis.find( unoName ) ); + if (iiFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#ifdef DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iiFind->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + terminate(); + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + terminate(); + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno ) +{ + OSL_ENSURE( header, "### no exception header!!!" ); + if (! header) + terminate(); + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" ); + if (! pExcTypeDescr) + terminate(); + + // construct uno exception any + ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + ::typelib_typedescription_release( pExcTypeDescr ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_powerpc/makefile.mk b/bridges/source/cpp_uno/gcc3_macosx_powerpc/makefile.mk new file mode 100644 index 000000000000..381d39c607c1 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCMACOSXPgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj + + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS= $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) \ + -ldl + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_macosx_powerpc/share.hxx b/bridges/source/cpp_uno/gcc3_macosx_powerpc/share.hxx new file mode 100644 index 000000000000..4ec09c29ff0a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/share.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + + void dummy_can_throw_anything( char const * ); + + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_powerpc/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_macosx_powerpc/uno2cpp.cxx new file mode 100644 index 000000000000..fdc30b3756b8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/uno2cpp.cxx @@ -0,0 +1,637 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sys/types.h> +#include <sys/malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + char * pPT, + sal_Int32 * pStackLongs, + sal_Int32 /* nStackLongs */) +{ + + // parameter list is mixed list of * and values + // reference parameters are pointers + + // the basic idea here is to use gpr[8] as a storage area for + // the future values of registers r3 to r10 needed for the call, + // and similarly fpr[13] as a storage area for the future values + // of floating point registers f1 to f13 + + unsigned long * mfunc; // actual function to be invoked + void (*ptr)(); + int gpr[8]; // storage for gpregisters, map to r3-r10 + int off; // offset used to find function + double fpr[13]; // storage for fpregisters, map to f1-f13 + int n; // number of gprs mapped so far + int f; // number of fprs mapped so far + volatile long *p; // pointer to parameter overflow area + int c; // character of parameter type being decoded + volatile double dret; // temporary function return values + volatile int iret, iret2; + + // Because of the Power PC calling conventions we could be passing + // parameters in both register types and on the stack. To create the + // stack parameter area we need we now simply allocate local + // variable storage param[] that is at least the size of the parameter stack + // (more than enough space) which we can overwrite the parameters into. + + // Note: This keeps us from having to decode the signature twice and + // prevents problems with later local variables. + + // FIXME: I do not believe the following is true but we will keep the + // FIXME: extra space just to be safe until proven otherwise + + // Note: could require up to 2*nStackLongs words of parameter stack area + // if the call has many float parameters (i.e. floats take up only 1 + // word on the stack but take 2 words in parameter area in the + // stack frame . + + + // unsigned long param[(2*nStackLongs)]; + + /* now begin to load the C++ function arguments into storage */ + n = 0; + f = 0; + + + /* set up a pointer to the stack parameter area */ + __asm__ ( "addi %0,r1,24" : "=r" (p) : /* no inputs */ ); + + // #i94421#, work around compiler error: + volatile long * pCopy = p; + (void) pCopy; // avoid warning about unused variable + + // never called + // if (! pAdjustedThisPtr )CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + + // now we need to parse the entire signature string + // until we get the END indicator + + // treat complex return pointer like any other parameter + + // parse the argument list up to the ending ) + + while (*pPT != 'X') { + c = *pPT; + switch (c) { + + case 'D': /* type is double */ + if (f < 13) { + fpr[f++] = *((double *)pStackLongs); /* store in register */ + n+=2; + p+=2; + } else { + *p++ = *pStackLongs; /* or on the parameter stack */ + *p++ = *(pStackLongs + 1); + } + pStackLongs += 2; + break; + + case 'F': /* type is float */ + /* floats are stored as 1 32 bit word on param stack */ + if (f < 13) { + fpr[f++] = *((float *)pStackLongs); + n+=1; + p++; + } else { + *((float *)p) = *((float *)pStackLongs); + p += 1; + } + pStackLongs += 1; + break; + + case 'H': /* type is long long */ + if (n < 8) + { + gpr[n++] = *pStackLongs; + p++; + } + else + *p++ = *pStackLongs; + if(n < 8) + { + gpr[n++] = *(pStackLongs+1); + p++; + } + else + *p++ = *(pStackLongs+1); + pStackLongs += 2; + break; + + case 'S': + if (n < 8) { + gpr[n++] = *((unsigned short*)pStackLongs); + p++; + } else { + *p++ = *((unsigned short *)pStackLongs); + } + pStackLongs += 1; + break; + + case 'B': + if (n < 8) { + gpr[n++] = *((char *)pStackLongs); + p++; + } else { + *p++ = *((char *)pStackLongs); + } + pStackLongs += 1; + break; + + default: + if (n < 8) { + gpr[n++] = *pStackLongs; + p++; + } else { + *p++ = *pStackLongs; + } + pStackLongs += 1; + break; + } + pPT++; + } + + + /* figure out the address of the function we need to invoke */ + off = nVtableIndex; + off = off * 4; // 4 bytes per slot + mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable + mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset + mfunc = *((unsigned long **)mfunc); // the function is stored at the address + ptr = (void (*)())mfunc; + + /* Set up the machine registers and invoke the function */ + + __asm__ __volatile__ ( + "lwz r3, 0(%0)\n\t" + "lwz r4, 4(%0)\n\t" + "lwz r5, 8(%0)\n\t" + "lwz r6, 12(%0)\n\t" + "lwz r7, 16(%0)\n\t" + "lwz r8, 20(%0)\n\t" + "lwz r9, 24(%0)\n\t" + "lwz r10, 28(%0)\n\t" + "lfd f1, 0(%1)\n\t" + "lfd f2, 8(%1)\n\t" + "lfd f3, 16(%1)\n\t" + "lfd f4, 24(%1)\n\t" + "lfd f5, 32(%1)\n\t" + "lfd f6, 40(%1)\n\t" + "lfd f7, 48(%1)\n\t" + "lfd f8, 56(%1)\n\t" + "lfd f9, 64(%1)\n\t" + "lfd f10, 72(%1)\n\t" + "lfd f11, 80(%1)\n\t" + "lfd f12, 88(%1)\n\t" + "lfd f13, 96(%1)\n\t" + : : "r" (gpr), "r" (fpr) + : "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "f13" + ); + + (*ptr)(); + + + __asm__ __volatile__ ( + "stw r3, %1\n\t" + "stw r4, %2\n\t" + "stfd f1, %0\n\t" + : : "m" (dret), "m" (iret), "m" (iret2) + ); + + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = iret2; + // fall thru on purpose + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = iret; + break; + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)iret; + break; + + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)iret; + break; + + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = (float)dret; + break; + + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = dret; + break; + default: + break; + } +} + + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // need to know parameter types for callVirtualMethod so generate a signature string + char * pParamType = (char *) alloca(nParams+2); + char * pPT = pParamType; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + *pPT++ = 'C'; //signify that a complex return type on stack + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + *pPT++ = 'I'; + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + + // we need to know type of each param so that we know whether to use + // gpr or fpr to pass in parameters: + // Key: I - int, long, pointer, etc means pass in gpr + // B - byte value passed in gpr + // S - short value passed in gpr + // F - float value pass in fpr + // D - double value pass in fpr + // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc + // X - indicates end of parameter description string + + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pPT++ = 'I'; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + *pPT++ = 'S'; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *pPT++ = 'B'; + break; + case typelib_TypeClass_FLOAT: + *pPT++ = 'F'; + break; + case typelib_TypeClass_DOUBLE: + *pPT++ = 'D'; + pCppStack += sizeof(sal_Int32); // extra long + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *pPT++ = 'H'; + pCppStack += sizeof(sal_Int32); // extra long + default: + break; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + *pPT++='I'; + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // terminate the signature string + *pPT++='X'; + *pPT=0; + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * > (pUnoI); + // typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; //get then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx new file mode 100644 index 000000000000..7b960f238508 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx @@ -0,0 +1,526 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[1]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack ) + __attribute__((regparm(3))); + +void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** pCallStack ) +{ + volatile long nRegReturn[2]; + typelib_TypeClass aType = cpp_mediate( + nFunctionIndex, nVtableOffset, pCallStack, (sal_Int64*)nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "movl %1, %%edx\n\t" + "movl %0, %%eax\n" + : : "m"(nRegReturn[0]), "m"(nRegReturn[1]) ); + break; + case typelib_TypeClass_FLOAT: + __asm__( "flds %0\n\t" + "fstp %%st(0)\n\t" + "flds %0\n" + : : "m"(*(float *)nRegReturn) ); + break; + case typelib_TypeClass_DOUBLE: + __asm__( "fldl %0\n\t" + "fstp %%st(0)\n\t" + "fldl %0\n" + : : "m"(*(double *)nRegReturn) ); + break; +// case typelib_TypeClass_UNSIGNED_SHORT: +// case typelib_TypeClass_SHORT: +// __asm__( "movswl %0, %%eax\n" +// : : "m"(nRegReturn) ); +// break; + default: + __asm__( "movl %0, %%eax\n" + : : "m"(nRegReturn[0]) ); + break; + } +} + + +//================================================================================================== +int const codeSnippetSize = 20; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) +{ + if (!simpleRetType) { + functionIndex |= 0x80000000; + } + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov function_index, %eax: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov vtable_offset, %edx: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // mov %esp, %ecx: + *p++ = 0x89; + *p++ = 0xE1; + // jmp cpp_vtable_call: + *p++ = 0xE9; + *reinterpret_cast< sal_Int32 * >(p) + = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32); + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/except.cxx b/bridges/source/cpp_uno/gcc3_solaris_intel/except.cxx new file mode 100644 index 000000000000..4779b145ab06 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/except.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_solaris_intel/makefile.mk new file mode 100644 index 000000000000..ccc0cb9e0402 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCSOLARISIgcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/share.hxx b/bridges/source/cpp_uno/gcc3_solaris_intel/share.hxx new file mode 100644 index 000000000000..da2367ad172b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/share.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_solaris_intel/uno2cpp.cxx new file mode 100644 index 000000000000..97dfe64ee32a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/uno2cpp.cxx @@ -0,0 +1,430 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> +#include <sal/alloca.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + // copy values + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + } +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx new file mode 100644 index 000000000000..87ee5cc93ad6 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx @@ -0,0 +1,567 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/data.h> +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" +#include "share.hxx" +#include <sal/alloca.h> + +using namespace com::sun::star::uno; + +namespace +{ +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: [ret ptr], this, params + char * pCppStack = (char *)pCallStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void**)pCppStack; + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + pCppStack += sizeof( void* ); + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { + pCppArgs[nPos] = pUnoArgs[nPos] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr); + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + { + if ((reinterpret_cast< long >(pCppStack) & 7) != 0) + { + OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) ); + void * pDest = alloca( sizeof (sal_Int64) ); + *reinterpret_cast< sal_Int32 * >(pDest) = + *reinterpret_cast< sal_Int32 const * >(pCppStack); + *(reinterpret_cast< sal_Int32 * >(pDest) + 1) = + *(reinterpret_cast< sal_Int32 const * >(pCppStack) + 1); + pCppArgs[nPos] = pUnoArgs[nPos] = pDest; + } + pCppStack += sizeof (sal_Int32); // extra long + break; + } + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +//================================================================================================== +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: this, params + // eventual [ret*] lies at pCallStack -1 + // so count down pCallStack by one to keep it simple + // pCallStack: this, params + // eventual [ret*] lies at pCallStack -1 + // so count down pCallStack by one to keep it simple + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + static_cast< char * >(*pCallStack) - nVtableOffset); + if ((nFunctionIndex & 0x80000000) != 0) { + nFunctionIndex &= 0x7FFFFFFF; + --pCallStack; + } + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), (XInterface *)pCppI ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); +#endif + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), (XInterface *)pCppI ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + return eRet; +} + + + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call() +{ + volatile sal_Int64 nRegReturn; + int nFunctionIndex; + void** pCallStack; + int vTableOffset; + + __asm__( "st %%i0, %0\n\t" + "st %%i1, %1\n\t" + "st %%i2, %2\n\t" + : : "m"(nFunctionIndex), "m"(pCallStack), "m"(vTableOffset) ); + +// fprintf(stderr,"cpp_mediate nFunctionIndex=%x\n",nFunctionIndex); +// fflush(stderr); + + sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, vTableOffset, pCallStack+17, (sal_Int64*)&nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "ld %0, %%l0\n\t" + "ldsb [%%l0], %%i0\n" + : : "m"(&nRegReturn) ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "ld %0, %%l0\n\t" + "ldsh [%%l0], %%i0\n" + : : "m"(&nRegReturn) ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%i0\n\t" + "ld %1, %%l0\n\t" + "ld [%%l0], %%i1\n\t" + : : "m"(&nRegReturn), "m"(((long*)&nRegReturn) +1) ); + + break; + case typelib_TypeClass_FLOAT: + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%f0\n" + : : "m"(&nRegReturn) ); + break; + case typelib_TypeClass_DOUBLE: + __asm__( "ld %0, %%l0\n\t" + "ldd [%%l0], %%f0\n" + : : "m"(&nRegReturn) ); + break; + case typelib_TypeClass_VOID: + break; + default: + __asm__( "ld %0, %%l0\n\t" + "ld [%%l0], %%i0\n" + : : "m"(&nRegReturn) ); + break; + } + + if( bComplex ) + { + __asm__( "add %i7, 4, %i7\n\t" ); + // after call to complex return valued funcion there is an unimp instruction + } + +} +//__________________________________________________________________________________________________ + +int const codeSnippetSize = 56; +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool simpleRetType) +{ + sal_uInt32 index = functionIndex; + if (!simpleRetType) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + OSL_ASSERT(sizeof (unsigned int) == 4); + // st %o0, [%sp+68]: + *p++ = 0xD023A044; + // st %o1, [%sp+72]: + *p++ = 0xD223A048; + // st %o2, [%sp+76]: + *p++ = 0xD423A04C; + // st %o3, [%sp+80]: + *p++ = 0xD623A050; + // st %o4, [%sp+84]: + *p++ = 0xD823A054; + // st %o5, [%sp+88]: + *p++ = 0xDA23A058; + // sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // sethi %hi(vtableOffset), %o2: + *p++ = 0x15000000 | (vtableOffset >> 10); + // or %o2, %lo(vtableOffset), %o2: + *p++ = 0x9412A000 | (vtableOffset & 0x3FF); + // sethi %hi(cpp_vtable_call), %o3: + *p++ = 0x17000000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) >> 10); + // or %o3, %lo(cpp_vtable_call), %o3: + *p++ = 0x9612E000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) & 0x3FF); + // jmpl %o3, %g0: + *p++ = 0x81C2C000; + // mov %sp, %o1: + *p++ = 0x9210000E; + OSL_ASSERT( + reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} //end of namespace + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; //null + slots[-1].fn = 0; //destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vTableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vTableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vTableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vTableOffset, + bridges::cpp_uno::shared::isSimpleType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) + { + //TODO: IZ 25819 flush the instruction cache (there probably is OS support for this) + } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/except.cxx b/bridges/source/cpp_uno/gcc3_solaris_sparc/except.cxx new file mode 100644 index 000000000000..fef8c3facada --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/except.cxx @@ -0,0 +1,329 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <stdio.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if defined BRIDGES_DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if defined BRIDGES_DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ + dlclose( m_hApp ); +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with _ZTI + char const * rttiName = symName.getStr() +4; +#if defined BRIDGES_DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if defined BRIDGES_DEBUG + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if defined BRIDGES_DEBUG + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if defined _DEBUG + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/makefile.mk b/bridges/source/cpp_uno/gcc3_solaris_sparc/makefile.mk new file mode 100644 index 000000000000..2fcc5fbdd8d8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)$(OS)$(CPU)" == "GCCSOLARISS" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSNOOPT=-O0 + +NOOPTFILES = \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/cpp2uno.obj + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + + +SHL1TARGET=$(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS= $(SLOFILES) +SHL1LIBS =$(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/share.hxx b/bridges/source/cpp_uno/gcc3_solaris_sparc/share.hxx new file mode 100644 index 000000000000..3526f19082cd --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/share.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "uno/mapping.h" +#include <typeinfo> +#include <exception> +#include <cstddef> +namespace CPPU_CURRENT_NAMESPACE +{ +void dummy_can_throw_anything( char const * ); +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); + +inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType ) +{ + switch( pType->nSize ) + { + case 1: return pIn + 3; + case 2: return pIn + 2; + case 3: return pIn + 1; + // Huh ? perhaps a char[3] ? Though that would be a pointer + // well, we have it anyway for symmetry + } + return pIn; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_solaris_sparc/uno2cpp.cxx new file mode 100644 index 000000000000..81dbb5dcea53 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/uno2cpp.cxx @@ -0,0 +1,601 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <malloc.h> +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#include <sal/alloca.h> + +using namespace com::sun::star::uno; + +using ::rtl::OUString; +using ::rtl::OString; +using ::rtl::OUStringToOString; + +namespace +{ +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && + (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long o0 = 0, o1 = 0; // for register returns + volatile double f0d = 0; + volatile float f0f = 0; + volatile long long saveReg[7]; + + __asm__ ( + // save registers + "std %%l0, [%4]\n\t" + "mov %4, %%l0\n\t" + "mov %%l0, %%l1\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o0, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%o4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "std %%l6, [%%l0]\n\t" + "mov %%l1, %%l7\n\t" + + // increase our own stackframe if necessary + "mov %%sp, %%l3\n\t" // save stack ptr for readjustment + + "subcc %%i5, 7, %%l0\n\t" + "ble .LmoveOn\n\t" + "nop\n\t" + + "sll %%l0, 2, %%l0\n\t" + "add %%l0, 96, %%l0\n\t" + "mov %%sp, %%l1\n\t" // old stack ptr + "sub %%sp, %%l0, %%l0\n\t" // future stack ptr + "andcc %%l0, 7, %%g0\n\t" // align stack to 8 + "be .LisAligned\n\t" + "nop\n\t" + "sub %%l0, 4, %%l0\n" + ".LisAligned:\n\t" + "mov %%l0, %%o5\n\t" // save newly computed stack ptr + "add %%g0, 16, %%o4\n" + + // now copy longs down to save register window + // and local variables + ".LcopyDown:\n\t" + "ld [%%l1], %%l2\n\t" + "st %%l2,[%%l0]\n\t" + "add %%l0, 4, %%l0\n\t" + "add %%l1, 4, %%l1\n\t" + "subcc %%o4, 1, %%o4\n\t" + "bne .LcopyDown\n\t" + + "mov %%o5, %%sp\n\t" // move new stack ptr (hopefully) atomically + // while register window is valid in both spaces + // (scheduling might hit in copyDown loop) + + "sub %%i5, 7, %%l0\n\t" // copy parameters past the sixth to stack + "add %%i4, 28, %%l1\n\t" + "add %%sp, 92, %%l2\n" + ".LcopyLong:\n\t" + "ld [%%l1], %%o0\n\t" + "st %%o0, [%%l2]\n\t" + "add %%l1, 4, %%l1\n\t" + "add %%l2, 4, %%l2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "bne .LcopyLong\n\t" + "nop\n" + + ".LmoveOn:\n\t" + "mov %%i5, %%l0\n\t" // prepare out registers + "mov %%i4, %%l1\n\t" + + "ld [%%l1], %%o0\n\t" // prepare complex return ptr + "st %%o0, [%%sp+64]\n\t" + "sub %%l0, 1, %%l0\n\t" + "add %%l1, 4, %%l1\n\t" + + "ld [%%l1], %%o0\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o1\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o3\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o4\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 4, %%l1\n\t" + "ld [%%l1], %%o5\n" + + ".LdoCall:\n\t" + "ld [%%i0], %%l0\n\t" // get vtable ptr + +"sll %%i1, 2, %%l6\n\t" +// "add %%l6, 8, %%l6\n\t" + "add %%l6, %%l0, %%l0\n\t" +// // vtable has 8byte wide entries, +// // upper half contains 2 half words, of which the first +// // is the this ptr patch ! +// // first entry is (or __tf) + +// "ldsh [%%l0], %%l6\n\t" // load this ptr patch +// "add %%l6, %%o0, %%o0\n\t" // patch this ptr + +// "add %%l0, 4, %%l0\n\t" // get virtual function ptr + "ld [%%l0], %%l0\n\t" + + "ld [%%i4], %%l2\n\t" + "subcc %%l2, %%g0, %%l2\n\t" + "bne .LcomplexCall\n\t" + "nop\n\t" + "call %%l0\n\t" + "nop\n\t" + "ba .LcallReturned\n\t" + "nop\n" + ".LcomplexCall:\n\t" + "call %%l0\n\t" + "nop\n\t" + "unimp\n" + + ".LcallReturned:\n\t" + "mov %%l3, %%sp\n\t" // readjust stack so that our locals are where they belong + "st %%o0, %0\n\t" // save possible return registers into our locals + "st %%o1, %1\n\t" + "std %%f0, %2\n\t" + "st %%f0, %3\n\t" + + // restore registers + "ldd [%%l7], %%l0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%o4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldd [%%l7], %%l6\n\t" + : : + "m"(o0), + "m"(o1), + "m"(f0d), + "m"(f0f), + "r"(&saveReg[0]) + ); + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = o1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = o0; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)o0; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)o0; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = f0f; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = f0d; + break; + } +} + +//================================================================================================= +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: complex ret ptr, this, values|ptr ... + char * pCppStack = + (char *)alloca( (nParams+2) * sizeof(sal_Int64) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + *(void**)pCppStack = NULL; + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + } + pCppStack += sizeof(void*); + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) ); + *reinterpret_cast< sal_Int32 * >(pCppStack) = + *reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ]); + pCppStack += sizeof (sal_Int32); + *reinterpret_cast< sal_Int32 * >(pCppStack) = + *(reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ] ) + 1); + break; + default: + uno_copyAndConvertData( + pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic" ); + + if( nStackLongs & 1 ) + // stack has to be 8 byte aligned + nStackLongs++; + callVirtualMethod( + pAdjustedThisPtr, + aVtableSlot.index, + pCppReturn, + pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, + nStackLongs); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch( ... ) + { + // get exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() ); +#endif + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/call.s b/bridges/source/cpp_uno/mingw_intel/call.s new file mode 100644 index 000000000000..47327d9a4650 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/call.s @@ -0,0 +1,261 @@ + .text + +.globl _privateSnippetExecutorGeneral +_privateSnippetExecutorGeneral: +.LFBg: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIg0: + movl %esp,%ebp +.LCFIg1: + subl $0x4,%esp # 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + movl 16(%esp),%eax # 32bit returnValue + leave + ret +.LFEg: + .long .-_privateSnippetExecutorGeneral + +.globl _privateSnippetExecutorVoid +_privateSnippetExecutorVoid: +.LFBv: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIv0: + movl %esp,%ebp +.LCFIv1: + pushl $0 # 32bit null pointer (returnValue not used) + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + leave + ret +.LFEv: + .long .-_privateSnippetExecutorVoid + +.globl _privateSnippetExecutorHyper +_privateSnippetExecutorHyper: +.LFBh: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIh0: + movl %esp,%ebp +.LCFIh1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + movl 16(%esp),%eax # 64bit returnValue, lower half + movl 20(%esp),%edx # 64bit returnValue, upper half + leave + ret +.LFEh: + .long .-_privateSnippetExecutorHyper + +.globl _privateSnippetExecutorFloat +_privateSnippetExecutorFloat: +.LFBf: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIf0: + movl %esp,%ebp +.LCFIf1: + subl $0x4,%esp # 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + flds 16(%esp) # 32bit returnValue + leave + ret +.LFEf: + .long .-_privateSnippetExecutorFloat + +.globl _privateSnippetExecutorDouble +_privateSnippetExecutorDouble: +.LFBd: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFId0: + movl %esp,%ebp +.LCFId1: + subl $0x8,%esp # 64bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + fldl 16(%esp) # 64bit returnValue + leave + ret +.LFEd: + .long .-_privateSnippetExecutorDouble + +.globl _privateSnippetExecutorClass +_privateSnippetExecutorClass: +.LFBc: + movl %esp,%ecx + pushl %ebp # proper stack frame needed for exception handling +.LCFIc0: + movl %esp,%ebp +.LCFIc1: + subl $0x4,%esp # 32bit returnValue + pushl %esp # 32bit &returnValue + pushl %ecx # 32bit pCallStack + pushl %edx # 32bit nVtableOffset + pushl %eax # 32bit nFunctionIndex + call _cpp_vtable_call + movl 16(%esp),%eax # 32bit returnValue + leave + ret $4 +.LFEc: + .long .-_privateSnippetExecutorClass + + .section .eh_frame,"dr" +.Lframe1: + .long .LECIE1-.LSCIE1 # length +.LSCIE1: + .long 0 # CIE_ID + .byte 1 # version + .string "zR" # augmentation + .uleb128 1 # code_alignment_factor + .sleb128 -4 # data_alignment_factor + .byte 8 # return_address_register + .uleb128 1 # augmentation size 1: + .byte 0x1B # FDE Encoding (pcrel sdata4) + # initial_instructions: + .byte 0x0C # DW_CFA_def_cfa %esp, 4 + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset ret, 1 + .uleb128 1 + .align 4 +.LECIE1: +.LSFDEg: + .long .LEFDEg-.LASFDEg # length +.LASFDEg: + .long .LASFDEg-.Lframe1 # CIE_pointer + .long .LFBg-. # initial_location + .long .LFEg-.LFBg # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIg0-.LFBg + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIg1-.LCFIg0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEg: +.LSFDEv: + .long .LEFDEv-.LASFDEv # length +.LASFDEv: + .long .LASFDEv-.Lframe1 # CIE_pointer + .long .LFBv-. # initial_location + .long .LFEv-.LFBv # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIv0-.LFBv + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIv1-.LCFIv0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEv: +.LSFDEh: + .long .LEFDEh-.LASFDEh # length +.LASFDEh: + .long .LASFDEh-.Lframe1 # CIE_pointer + .long .LFBh-. # initial_location + .long .LFEh-.LFBh # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIh0-.LFBh + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIh1-.LCFIh0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEh: +.LSFDEf: + .long .LEFDEf-.LASFDEf # length +.LASFDEf: + .long .LASFDEf-.Lframe1 # CIE_pointer + .long .LFBf-. # initial_location + .long .LFEf-.LFBf # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIf0-.LFBf + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIf1-.LCFIf0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEf: +.LSFDEd: + .long .LEFDEd-.LASFDEd # length +.LASFDEd: + .long .LASFDEd-.Lframe1 # CIE_pointer + .long .LFBd-. # initial_location + .long .LFEd-.LFBd # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFId0-.LFBd + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFId1-.LCFId0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEd: +.LSFDEc: + .long .LEFDEc-.LASFDEc # length +.LASFDEc: + .long .LASFDEc-.Lframe1 # CIE_pointer + .long .LFBc-. # initial_location + .long .LFEc-.LFBc # address_range + .uleb128 0 # augmentation size 0 + # instructions: + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIc0-.LFBc + .byte 0x0E # DW_CFA_def_cfa_offset 8 + .uleb128 8 + .byte 0x85 # DW_CFA_offset %ebp, 2 + .uleb128 2 + .byte 0x04 # DW_CFA_advance_loc4 + .long .LCFIc1-.LCFIc0 + .byte 0x0D # DW_CFA_def_cfa_register %ebp + .uleb128 5 + .align 4 +.LEFDEc: diff --git a/bridges/source/cpp_uno/mingw_intel/cpp2uno.cxx b/bridges/source/cpp_uno/mingw_intel/cpp2uno.cxx new file mode 100644 index 000000000000..8bde24c63da0 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/cpp2uno.cxx @@ -0,0 +1,521 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <typelib/typedescription.hxx> +#include <sal/alloca.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "share.hxx" +#include "smallstruct.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +void cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + void * pReturnValue ) +{ + // pCallStack: ret, [return ptr], this, params + char * pCppStack = (char *)(pCallStack +1); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pReturnValue; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + if (!bridges::cpp_uno::shared::isSmallStruct(pReturnTypeDescr)) { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + } + else { + pCppReturn = pReturnValue; + } + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + CPPU_CURRENT_NAMESPACE::raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + if (pReturnValue != pCppReturn) + // complex return ptr is set to eax + *static_cast< void ** >(pReturnValue) = pCppReturn; + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + } +} + + +//================================================================================================== +extern "C" void cpp_vtable_call( + int nFunctionIndex, int nVtableOffset, void** pCallStack, + void * pReturnValue ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + void * pThis; + if( nFunctionIndex & 0x80000000 ) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[2]; + } + else + { + pThis = pCallStack[1]; + } + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pReturnValue ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pReturnValue ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[1] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *static_cast< void ** >(pReturnValue) = pCallStack[1]; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pReturnValue ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )), + (XInterface *)pThis ); + } + } +} + +//================================================================================================== +extern "C" void privateSnippetExecutorGeneral(); +extern "C" void privateSnippetExecutorVoid(); +extern "C" void privateSnippetExecutorHyper(); +extern "C" void privateSnippetExecutorFloat(); +extern "C" void privateSnippetExecutorDouble(); +extern "C" void privateSnippetExecutorClass(); +extern "C" typedef void (*PrivateSnippetExecutor)(); + +int const codeSnippetSize = 16; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + typelib_TypeDescriptionReference * returnType) +{ + typelib_TypeDescription * returnTypeDescr = 0; + if (returnType) + TYPELIB_DANGER_GET( &returnTypeDescr, returnType ); + + typelib_TypeClass returnTypeClass = returnType ? returnType->eTypeClass : typelib_TypeClass_VOID; + if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass) && + !bridges::cpp_uno::shared::isSmallStruct(returnTypeDescr)) { + functionIndex |= 0x80000000; + } + PrivateSnippetExecutor exec; + switch (returnTypeClass) { + case typelib_TypeClass_VOID: + exec = privateSnippetExecutorVoid; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + exec = privateSnippetExecutorHyper; + break; + case typelib_TypeClass_FLOAT: + exec = privateSnippetExecutorFloat; + break; + case typelib_TypeClass_DOUBLE: + exec = privateSnippetExecutorDouble; + break; + case typelib_TypeClass_STRUCT: + if (bridges::cpp_uno::shared::isSmallStruct(returnTypeDescr)) { + if (returnType->pType->nSize <= 4) { + exec = privateSnippetExecutorGeneral; + } + else if (returnType->pType->nSize <= 8) { + exec = privateSnippetExecutorHyper; + } + } + else { + exec = privateSnippetExecutorClass; + } + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + exec = privateSnippetExecutorClass; + break; + default: + exec = privateSnippetExecutorGeneral; + break; + } + if (returnType) + TYPELIB_DANGER_RELEASE( returnTypeDescr ); + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov function_index, %eax: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov vtable_offset, %edx: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // jmp privateSnippetExecutor: + *p++ = 0xE9; + *reinterpret_cast< sal_Int32 * >(p) + = ((unsigned char *) exec) - p - sizeof (sal_Int32); + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + NULL); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/dllinit.cxx b/bridges/source/cpp_uno/mingw_intel/dllinit.cxx new file mode 100644 index 000000000000..d215a3124470 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/dllinit.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#include <windows.h> + + +void dso_init(void); +void dso_exit(void); + + +extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved) +{ + switch(dwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + + dso_init(); + break; + + case DLL_PROCESS_DETACH: + if (!lpvReserved) + dso_exit(); + break; + } + + return TRUE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/except.cxx b/bridges/source/cpp_uno/mingw_intel/except.cxx new file mode 100644 index 000000000000..5997c3b1ea2a --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/except.cxx @@ -0,0 +1,316 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <string.h> +#include <cxxabi.h> +#include <boost/unordered_map.hpp> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +//================================================================================================== +static OUString toUNOname( char const * p ) SAL_THROW( () ) +{ +#if OSL_DEBUG_LEVEL > 1 + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + OSL_ASSERT( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( (sal_Unicode)'.' ); + } + +#if OSL_DEBUG_LEVEL > 1 + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +//================================================================================================== +class RTTI +{ + typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + +public: + RTTI() SAL_THROW( () ); + ~RTTI() SAL_THROW( () ); + + type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +RTTI::RTTI() SAL_THROW( () ) +{ +} +//__________________________________________________________________________________________________ +RTTI::~RTTI() SAL_THROW( () ) +{ +} + +//__________________________________________________________________________________________________ +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); + if (iRttiFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( RTL_CONSTASCII_STRINGPARAM("__ZTIN") ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); + if (iFind == m_generatedRttis.end()) + { + // we must generate it ! + // symbol and rtti-name is nearly identical, + // the symbol is prefixed with __ZTI + char const * rttiName = symName.getStr() +5; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + if (pTypeDescr->pBaseTypeDescription) + { + // ensure availability of base + type_info * base_rtti = getRTTI( + (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); + rtti = new __si_class_type_info( + strdup( rttiName ), (__class_type_info *)base_rtti ); + } + else + { + // this class has no base class + rtti = new __class_type_info( strdup( rttiName ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); + } + else // taking already generated rtti + { + rtti = iFind->second; + } + } + else + { + rtti = iRttiFind->second; + } + + return rtti; +} + +//-------------------------------------------------------------------------------------------------- +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +//================================================================================================== +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if OSL_DEBUG_LEVEL > 1 + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + OSL_ASSERT( pTypeDescr ); + if (! pTypeDescr) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + + pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + // avoiding locked counts + static RTTI * s_rtti = 0; + if (! s_rtti) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_rtti) + { +#ifdef LEAK_STATIC_DATA + s_rtti = new RTTI(); +#else + static RTTI rtti_data; + s_rtti = &rtti_data; +#endif + } + } + rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); + if (! rtti) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + Reference< XInterface >() ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +//================================================================================================== +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() ); +#endif + typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); + if (0 == pExcTypeDescr) + { + RuntimeException aRE( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, + Reference< XInterface >() ); + Type const & rType = ::getCppuType( &aRE ); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/makefile.mk b/bridges/source/cpp_uno/mingw_intel/makefile.mk new file mode 100644 index 000000000000..6ff0cbe2da68 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/makefile.mk @@ -0,0 +1,97 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=gcc3_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)" == "GCC" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF +.IF "$(EXCEPTIONS)" == "sjlj" +CFLAGS += -DBROKEN_ALLOCA +.ENDIF + +# In case someone enabled the non-standard -fomit-frame-pointer which does not +# work with the .cxx sources in this directory: +CFLAGSCXX += -fno-omit-frame-pointer + +# In case the compiler supports AVX this code segfaults so specifically turn +# it off. +.IF "$(HAVE_GCC_AVX)" == "TRUE" + CFLAGSCXX+= -mno-avx +.ENDIF + +NOOPTFILES= \ + $(SLO)$/uno2cpp.obj + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/dllinit.obj \ + $(SLO)$/smallstruct.obj \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/call.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +DEF1NAME= $(SHL1TARGET) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s + $(CC) -c -o $(SLO)$/$(@:b).obj $< + touch $@ diff --git a/bridges/source/cpp_uno/mingw_intel/share.hxx b/bridges/source/cpp_uno/mingw_intel/share.hxx new file mode 100644 index 000000000000..da2367ad172b --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/share.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/mapping.h" + +#include <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ); + +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + ::std::unexpected_handler unexpectedHandler; + ::std::terminate_handler terminateHandler; + + __cxa_exception *nextException; + + int handlerCount; + + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +extern "C" void *__cxa_allocate_exception( + std::size_t thrown_size ) throw(); +extern "C" void __cxa_throw ( + void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// ----- + +//================================================================================================== +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); +//================================================================================================== +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/smallstruct.cxx b/bridges/source/cpp_uno/mingw_intel/smallstruct.cxx new file mode 100644 index 000000000000..bcfb0df87902 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/smallstruct.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/types.hxx" + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +namespace { +bool isSimpleStruct(typelib_TypeDescription const * type) { + switch (type->eTypeClass) { + case typelib_TypeClass_STRUCT: + { + typelib_CompoundTypeDescription const * p + = reinterpret_cast< typelib_CompoundTypeDescription const * >( + type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) { + switch (p->ppTypeRefs[i]->eTypeClass) { + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = isSimpleStruct(t); + TYPELIB_DANGER_RELEASE(t); + if (!b) { + return false; + } + } + break; + + default: + if (!isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return false; + break; + } + } + } + return true; + + default: + return false; + } +} +} + +bool isSmallStruct(typelib_TypeDescription const * type) { + return (type->nSize <= 8 && isSimpleStruct(type)); +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/smallstruct.hxx b/bridges/source/cpp_uno/mingw_intel/smallstruct.hxx new file mode 100644 index 000000000000..f1eae96e6734 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/smallstruct.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +bool isSmallStruct(typelib_TypeDescription const * type); + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx b/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx new file mode 100644 index 000000000000..4dd6cdefd083 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx @@ -0,0 +1,503 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <com/sun/star/uno/genfunc.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" +#include <uno/data.h> +#include <sal/alloca.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" +#include "smallstruct.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription const * returnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescription const * returnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + // copy values + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + switch( returnType->eTypeClass ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_STRUCT: + if (bridges::cpp_uno::shared::isSmallStruct(returnType)) { + if (returnType->nSize <= 1) { + *(unsigned char*)pRegisterReturn = eax; + } + else if (returnType->nSize <= 2) { + *(unsigned short*)pRegisterReturn = eax; + } + else if (returnType->nSize <= 8) { + ((long*)pRegisterReturn)[0] = eax; + if (returnType->nSize > 4) { + ((long*)pRegisterReturn)[1] = edx; + } + } + } + break; + default: + break; + } +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = +#ifdef BROKEN_ALLOCA + (char *)malloc( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); +#else + (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); +#endif + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) +#ifdef BROKEN_ALLOCA + ? malloc( pReturnTypeDescr->nSize ) +#else + ? alloca( pReturnTypeDescr->nSize ) +#endif + : pUnoReturn); // direct way + if (!bridges::cpp_uno::shared::isSmallStruct(pReturnTypeDescr)) { + *(void **)pCppStack = pCppReturn; + pCppStack += sizeof(void *); + } + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args +#ifdef BROKEN_ALLOCA + void ** pCppArgs = (void **)malloc( 3 * sizeof(void *) * nParams ); +#else + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); +#endif + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( +#ifdef BROKEN_ALLOCA + *(void **)pCppStack = pCppArgs[nPos] = malloc( pParamTypeDescr->nSize ), +#else + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), +#endif + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( +#ifdef BROKEN_ALLOCA + *(void **)pCppStack = pCppArgs[nPos] = malloc( pParamTypeDescr->nSize ), +#else + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), +#endif + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + try + { + OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeDescr, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); +#ifdef BROKEN_ALLOCA + free( pCppArgs[nIndex] ); +#endif + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndizes--; ) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); +#ifdef BROKEN_ALLOCA + free( pCppArgs[nIndex] ); +#endif + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + if (pCppReturn && pUnoReturn != pCppReturn) + { +#ifdef BROKEN_ALLOCA + free( pCppReturn ); +#endif + } +#ifdef BROKEN_ALLOCA + free( pCppStackStart ); +#endif +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx new file mode 100644 index 000000000000..106cb211b570 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -0,0 +1,489 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "msci.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static inline typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret, this, [complex return ptr], params + char * pCppStack = (char *)(pCallStack +2); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + { + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + } + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + + // stack space + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + ::uno_copyAndConvertData( + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + { + ::uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + } + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + + CPPU_CURRENT_NAMESPACE::msci_raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + ::uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + ::uno_copyAndConvertData( + pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + ::uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + ::uno_copyAndConvertData( + pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + ::uno_destructData( + pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + +//================================================================================================== +static typelib_TypeClass __cdecl cpp_mediate( + void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, this, [ret *], params + void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!") ), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet = typelib_TypeClass_VOID; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + // standard XInterface vtable calls + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[2] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[2]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("no member description found!") ), + (XInterface *)pThis ); + } + } + + return eRet; +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static __declspec(naked) void __cdecl cpp_vtable_call(void) +{ +__asm + { + sub esp, 8 // space for immediate return type + push esp + push edx // vtable offset + push eax // function index + mov eax, esp + add eax, 20 + push eax // original stack ptr + + call cpp_mediate + add esp, 16 + + cmp eax, typelib_TypeClass_FLOAT + je Lfloat + cmp eax, typelib_TypeClass_DOUBLE + je Ldouble + cmp eax, typelib_TypeClass_HYPER + je Lhyper + cmp eax, typelib_TypeClass_UNSIGNED_HYPER + je Lhyper + // rest is eax + pop eax + add esp, 4 + ret +Lhyper: + pop eax + pop edx + ret +Lfloat: + fld dword ptr [esp] + add esp, 8 + ret +Ldouble: + fld qword ptr [esp] + add esp, 8 + ret + } +} + +//================================================================================================== +int const codeSnippetSize = 16; + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset) +{ + unsigned char * p = code; + OSL_ASSERT(sizeof (sal_Int32) == 4); + // mov eax, functionIndex: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + // mov edx, vtableOffset: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + // jmp rel32 cpp_vtable_call: + *p++ = 0xE9; + *reinterpret_cast< sal_Int32 * >(p) + = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32); + p += sizeof (sal_Int32); + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + struct Rtti { + sal_Int32 n0, n1, n2; + type_info * rtti; + Rtti(): + n0(0), n1(0), n2(0), + rtti(CPPU_CURRENT_NAMESPACE::msci_getRTTI( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XInterface")))) + {} + }; + static Rtti rtti; + + Slot * slots = mapBlockToVtable(block); + slots[-1].fn = &rtti; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const *, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < functionCount; ++i) { + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/dllinit.cxx b/bridges/source/cpp_uno/msvc_win32_intel/dllinit.cxx new file mode 100644 index 000000000000..cfbc58650f0d --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/dllinit.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#pragma warning(push,1) // disable warnings within system headers +#include <windows.h> +#pragma warning(pop) + + +void dso_init(void); +void dso_exit(void); + + +extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved) +{ + switch(dwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + + dso_init(); + break; + + case DLL_PROCESS_DETACH: + if (!lpvReserved) + dso_exit(); + break; + } + + return TRUE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx new file mode 100644 index 000000000000..e8ac31ebf3a7 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx @@ -0,0 +1,634 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#pragma warning( disable : 4237 ) +#include <boost/unordered_map.hpp> +#include <sal/config.h> +#include <malloc.h> +#include <new.h> +#include <typeinfo.h> +#include <signal.h> + +#include "rtl/alloc.h" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/uno/Any.hxx" + +#include "msci.hxx" + + +#pragma pack(push, 8) + +using namespace ::com::sun::star::uno; +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +static inline OUString toUNOname( OUString const & rRTTIname ) throw () +{ + OUStringBuffer aRet( 64 ); + OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ + sal_Int32 nPos = aStr.getLength(); + while (nPos > 0) + { + sal_Int32 n = aStr.lastIndexOf( '@', nPos ); + aRet.append( aStr.copy( n +1, nPos -n -1 ) ); + if (n >= 0) + { + aRet.append( (sal_Unicode)'.' ); + } + nPos = n; + } + return aRet.makeStringAndClear(); +} +//================================================================================================== +static inline OUString toRTTIname( OUString const & rUNOname ) throw () +{ + OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU" + sal_Int32 nPos = rUNOname.getLength(); + while (nPos > 0) + { + sal_Int32 n = rUNOname.lastIndexOf( '.', nPos ); + aRet.append( rUNOname.copy( n +1, nPos -n -1 ) ); + aRet.append( (sal_Unicode)'@' ); + nPos = n; + } + aRet.append( (sal_Unicode)'@' ); + return aRet.makeStringAndClear(); +} + + +//################################################################################################## +//#### RTTI simulation ############################################################################# +//################################################################################################## + + +typedef boost::unordered_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap; + +//================================================================================================== +class RTTInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRTTI; + + static OUString toRawName( OUString const & rUNOname ) throw (); +public: + type_info * getRTTI( OUString const & rUNOname ) throw (); + + RTTInfos(); + ~RTTInfos(); +}; + +//================================================================================================== +class __type_info +{ + friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); + friend int msci_filterCppException( + LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * ); + +public: + virtual ~__type_info() throw (); + + inline __type_info( void * m_data, const char * m_d_name ) throw () + : _m_data( m_data ) + { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked + +private: + void * _m_data; + char _m_d_name[1]; +}; +//__________________________________________________________________________________________________ +__type_info::~__type_info() throw () +{ +} +//__________________________________________________________________________________________________ +type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () +{ + // a must be + OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" ); + + MutexGuard aGuard( _aMutex ); + t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) ); + + // check if type is already available + if (iFind == _allRTTI.end()) + { + // insert new type_info + OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) ); + __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) ) + __type_info( NULL, aRawName.getStr() ); + + // put into map + pair< t_string2PtrMap::iterator, bool > insertion( + _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) ); + OSL_ENSURE( insertion.second, "### rtti insertion failed?!" ); + + return (type_info *)pRTTI; + } + else + { + return (type_info *)iFind->second; + } +} +//__________________________________________________________________________________________________ +RTTInfos::RTTInfos() throw () +{ +} +//__________________________________________________________________________________________________ +RTTInfos::~RTTInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing generated RTTI infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() ); + iPos != _allRTTI.end(); ++iPos ) + { + __type_info * pType = (__type_info *)iPos->second; + pType->~__type_info(); // obsolete, but good style... + ::rtl_freeMemory( pType ); + } +} + + +//################################################################################################## +//#### Exception raising ########################################################################### +//################################################################################################## + + +//================================================================================================== +struct ObjectFunction +{ + char somecode[12]; + typelib_TypeDescription * _pTypeDescr; // type of object + + inline static void * operator new ( size_t nSize ); + inline static void operator delete ( void * pMem ); + + ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw (); + ~ObjectFunction() throw (); +}; + +inline void * ObjectFunction::operator new ( size_t nSize ) +{ + void * pMem = rtl_allocateMemory( nSize ); + if (pMem != 0) + { + DWORD old_protect; +#if OSL_DEBUG_LEVEL > 0 + BOOL success = +#endif + VirtualProtect( pMem, nSize, PAGE_EXECUTE_READWRITE, &old_protect ); + OSL_ENSURE( success, "VirtualProtect() failed!" ); + } + return pMem; +} + +inline void ObjectFunction::operator delete ( void * pMem ) +{ + rtl_freeMemory( pMem ); +} + +//__________________________________________________________________________________________________ +ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw () + : _pTypeDescr( pTypeDescr ) +{ + ::typelib_typedescription_acquire( _pTypeDescr ); + + unsigned char * pCode = (unsigned char *)somecode; + // a must be! + OSL_ENSURE( (void *)this == (void *)pCode, "### unexpected!" ); + + // push ObjectFunction this + *pCode++ = 0x68; + *(void **)pCode = this; + pCode += sizeof(void *); + // jmp rel32 fpFunc + *pCode++ = 0xe9; + *(sal_Int32 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int32); +} +//__________________________________________________________________________________________________ +ObjectFunction::~ObjectFunction() throw () +{ + ::typelib_typedescription_release( _pTypeDescr ); +} + +//================================================================================================== +static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis ) + throw () +{ + ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire ); + return pExcThis; +} +//================================================================================================== +static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis ) + throw () +{ + ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + return pExcThis; +} + +// these are non virtual object methods; there is no this ptr on stack => ecx supplies _this_ ptr + +//================================================================================================== +static __declspec(naked) void copyConstruct() throw () +{ + __asm + { + // ObjectFunction this already on stack + push [esp+8] // source exc object this + push ecx // exc object + call __copyConstruct + add esp, 12 // + ObjectFunction this + ret 4 + } +} +//================================================================================================== +static __declspec(naked) void destruct() throw () +{ + __asm + { + // ObjectFunction this already on stack + push ecx // exc object + call __destruct + add esp, 8 // + ObjectFunction this + ret + } +} + +//================================================================================================== +struct ExceptionType +{ + sal_Int32 _n0; + type_info * _pTypeInfo; + sal_Int32 _n1, _n2, _n3, _n4; + ObjectFunction * _pCopyCtor; + sal_Int32 _n5; + + inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw () + : _n0( 0 ) + , _n1( 0 ) + , _n2( -1 ) + , _n3( 0 ) + , _n4( pTypeDescr->nSize ) + , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) + , _n5( 0 ) + { _pTypeInfo = msci_getRTTI( pTypeDescr->pTypeName ); } + inline ~ExceptionType() throw () + { delete _pCopyCtor; } +}; +//================================================================================================== +struct RaiseInfo +{ + sal_Int32 _n0; + ObjectFunction * _pDtor; + sal_Int32 _n2; + void * _types; + sal_Int32 _n3, _n4; + + RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); + ~RaiseInfo() throw (); +}; +//__________________________________________________________________________________________________ +RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () + : _n0( 0 ) + , _pDtor( new ObjectFunction( pTypeDescr, destruct ) ) + , _n2( 0 ) + , _n3( 0 ) + , _n4( 0 ) +{ + // a must be + OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" ); + + typelib_CompoundTypeDescription * pCompTypeDescr; + + // info count + sal_Int32 nLen = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ++nLen; + } + + // info count accompanied by type info ptrs: type, base type, base base type, ... + _types = ::rtl_allocateMemory( sizeof(sal_Int32) + (sizeof(ExceptionType *) * nLen) ); + *(sal_Int32 *)_types = nLen; + + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); + + sal_Int32 nPos = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ppTypes[nPos++] = new ExceptionType( (typelib_TypeDescription *)pCompTypeDescr ); + } +} +//__________________________________________________________________________________________________ +RaiseInfo::~RaiseInfo() throw () +{ + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); + for ( sal_Int32 nTypes = *(sal_Int32 *)_types; nTypes--; ) + { + delete ppTypes[nTypes]; + } + ::rtl_freeMemory( _types ); + + delete _pDtor; +} + +//================================================================================================== +class ExceptionInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRaiseInfos; + +public: + static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); + + ExceptionInfos() throw (); + ~ExceptionInfos() throw (); +}; +//__________________________________________________________________________________________________ +ExceptionInfos::ExceptionInfos() throw () +{ +} +//__________________________________________________________________________________________________ +ExceptionInfos::~ExceptionInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing exception infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() ); + iPos != _allRaiseInfos.end(); ++iPos ) + { + delete (RaiseInfo *)iPos->second; + } +} +//__________________________________________________________________________________________________ +void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () +{ + static ExceptionInfos * s_pInfos = 0; + if (! s_pInfos) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pInfos) + { +#ifdef LEAK_STATIC_DATA + s_pInfos = new ExceptionInfos(); +#else + static ExceptionInfos s_allExceptionInfos; + s_pInfos = &s_allExceptionInfos; +#endif + } + } + + OSL_ASSERT( pTypeDescr && + (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || + pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) ); + + void * pRaiseInfo; + + OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName ); + MutexGuard aGuard( s_pInfos->_aMutex ); + t_string2PtrMap::const_iterator const iFind( + s_pInfos->_allRaiseInfos.find( rTypeName ) ); + if (iFind == s_pInfos->_allRaiseInfos.end()) + { + pRaiseInfo = new RaiseInfo( pTypeDescr ); + // put into map + pair< t_string2PtrMap::iterator, bool > insertion( + s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) ); + OSL_ENSURE( insertion.second, "### raise info insertion failed?!" ); + } + else + { + // reuse existing info + pRaiseInfo = iFind->second; + } + + return pRaiseInfo; +} + + +//################################################################################################## +//#### exported #################################################################################### +//################################################################################################## + + +//################################################################################################## +type_info * msci_getRTTI( OUString const & rUNOname ) +{ + static RTTInfos * s_pRTTIs = 0; + if (! s_pRTTIs) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pRTTIs) + { +#ifdef LEAK_STATIC_DATA + s_pRTTIs = new RTTInfos(); +#else + static RTTInfos s_aRTTIs; + s_pRTTIs = &s_aRTTIs; +#endif + } + } + return s_pRTTIs->getRTTI( rUNOname ); +} + +//################################################################################################## +void msci_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()! + // thus this obj file will be compiled without opt, so no inling of + // ExceptionInfos::getRaiseInfo() + + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + + void * pCppExc = alloca( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // a must be + OSL_ENSURE( + sizeof(sal_Int32) == sizeof(void *), + "### pointer size differs from sal_Int32!" ); + DWORD arFilterArgs[3]; + arFilterArgs[0] = MSVC_magic_number; + arFilterArgs[1] = (DWORD)pCppExc; + arFilterArgs[2] = (DWORD)ExceptionInfos::getRaiseInfo( pTypeDescr ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + + // last point to release anything not affected by stack unwinding + RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); +} + +//############################################################################## +int msci_filterCppException( + EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (pPointers == 0) + return EXCEPTION_CONTINUE_SEARCH; + EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord; + // handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + +#if _MSC_VER < 1300 // MSVC -6 + bool rethrow = (pRecord->NumberParameters < 3 || + pRecord->ExceptionInformation[ 2 ] == 0); +#else + bool rethrow = __CxxDetectRethrow( &pRecord ); + OSL_ASSERT( pRecord == pPointers->ExceptionRecord ); +#endif + if (rethrow && pRecord == pPointers->ExceptionRecord) + { + // hack to get msvcrt internal _curexception field: + pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >( + reinterpret_cast< char * >( __pxcptinfoptrs() ) + + // as long as we don't demand msvcr source as build prerequisite + // (->platform sdk), we have to code those offsets here. + // + // crt\src\mtdll.h: + // offsetof (_tiddata, _curexception) - + // offsetof (_tiddata, _tpxcptinfoptrs): +#if _MSC_VER < 1300 + 0x18 // msvcrt,dll +#elif _MSC_VER < 1310 + 0x20 // msvcr70.dll +#elif _MSC_VER < 1400 + 0x24 // msvcr71.dll +#else + 0x28 // msvcr80.dll +#endif + ); + } + // rethrow: handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + + if (pRecord->NumberParameters == 3 && +// pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number && + pRecord->ExceptionInformation[ 1 ] != 0 && + pRecord->ExceptionInformation[ 2 ] != 0) + { + void * types = reinterpret_cast< RaiseInfo * >( + pRecord->ExceptionInformation[ 2 ] )->_types; + if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count + { + ExceptionType * pType = *reinterpret_cast< ExceptionType ** >( + reinterpret_cast< DWORD * >( types ) + 1 ); + if (pType != 0 && pType->_pTypeInfo != 0) + { + OUString aRTTIname( + OStringToOUString( + reinterpret_cast< __type_info * >( + pType->_pTypeInfo )->_m_d_name, + RTL_TEXTENCODING_ASCII_US ) ); + OUString aUNOname( toUNOname( aRTTIname ) ); + + typelib_TypeDescription * pExcTypeDescr = 0; + typelib_typedescription_getByName( + &pExcTypeDescr, aUNOname.pData ); + if (pExcTypeDescr == 0) + { + OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "[msci_uno bridge error] UNO type of " + "C++ exception unknown: \"") ); + buf.append( aUNOname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\", RTTI-name=\"") ); + buf.append( aRTTIname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + RuntimeException exc( + buf.makeStringAndClear(), Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, + ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + // if (! rethrow): + // though this unknown exception leaks now, no user-defined + // exception is ever thrown thru the binary C-UNO dispatcher + // call stack. +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, (void *) pRecord->ExceptionInformation[1], + pExcTypeDescr, pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + if (! rethrow) + { + uno_destructData( + (void *) pRecord->ExceptionInformation[1], + pExcTypeDescr, cpp_release ); + } +#endif + typelib_typedescription_release( pExcTypeDescr ); + } + + return EXCEPTION_EXECUTE_HANDLER; + } + } + } + // though this unknown exception leaks now, no user-defined exception + // is ever thrown thru the binary C-UNO dispatcher call stack. + RuntimeException exc( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "[msci_uno bridge error] unexpected " + "C++ exception occurred!") ), + Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); + return EXCEPTION_EXECUTE_HANDLER; +} + +} + +#pragma pack(pop) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk b/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk new file mode 100644 index 000000000000..b4608cc70ac3 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=msci_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +.IF "$(COM)$(CPU)" == "MSCI" + +.IF "$(debug)" != "" +CFLAGS += -Ob0 +.ENDIF + +.IF "$(cppu_no_leak)" == "" +.IF "$(bndchk)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF +.ENDIF + + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/dllinit.obj \ + $(SLO)$/except.obj + +NOOPTFILES= \ + $(SLO)$/except.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +DEF1NAME=$(SHL1TARGET) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx new file mode 100644 index 000000000000..ecc4e22960d7 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#pragma warning(push, 1) +#include <windows.h> +#pragma warning(pop) + +#include "rtl/ustring.hxx" + + +class type_info; +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +namespace CPPU_CURRENT_NAMESPACE +{ + +const DWORD MSVC_ExceptionCode = 0xe06d7363; +const long MSVC_magic_number = 0x19930520L; + +//============================================================================== +type_info * msci_getRTTI( ::rtl::OUString const & rUNOname ); + +//============================================================================== +int msci_filterCppException( + EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); + +//============================================================================== +void msci_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx new file mode 100644 index 000000000000..547ee4c6873f --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx @@ -0,0 +1,468 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "msci.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +inline static void callVirtualMethod( + void * pAdjustedThisPtr, sal_Int32 nVtableIndex, + void * pRegisterReturn, typelib_TypeClass eReturnTypeClass, + sal_Int32 * pStackLongs, sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && + (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + +__asm + { + mov eax, nStackLongs + test eax, eax + je Lcall + // copy values + mov ecx, eax + shl eax, 2 // sizeof(sal_Int32) == 4 + add eax, pStackLongs // params stack space +Lcopy: sub eax, 4 + push dword ptr [eax] + dec ecx + jne Lcopy +Lcall: + // call + mov ecx, pAdjustedThisPtr + push ecx // this ptr + mov edx, [ecx] // pvft + mov eax, nVtableIndex + shl eax, 2 // sizeof(void *) == 4 + add edx, eax + call [edx] // interface method call must be __cdecl!!! + + // register return + mov ecx, eReturnTypeClass + cmp ecx, typelib_TypeClass_VOID + je Lcleanup + mov ebx, pRegisterReturn +// int32 + cmp ecx, typelib_TypeClass_LONG + je Lint32 + cmp ecx, typelib_TypeClass_UNSIGNED_LONG + je Lint32 + cmp ecx, typelib_TypeClass_ENUM + je Lint32 +// int8 + cmp ecx, typelib_TypeClass_BOOLEAN + je Lint8 + cmp ecx, typelib_TypeClass_BYTE + je Lint8 +// int16 + cmp ecx, typelib_TypeClass_CHAR + je Lint16 + cmp ecx, typelib_TypeClass_SHORT + je Lint16 + cmp ecx, typelib_TypeClass_UNSIGNED_SHORT + je Lint16 +// float + cmp ecx, typelib_TypeClass_FLOAT + je Lfloat +// double + cmp ecx, typelib_TypeClass_DOUBLE + je Ldouble +// int64 + cmp ecx, typelib_TypeClass_HYPER + je Lint64 + cmp ecx, typelib_TypeClass_UNSIGNED_HYPER + je Lint64 + jmp Lcleanup // no simple type +Lint8: + mov byte ptr [ebx], al + jmp Lcleanup +Lint16: + mov word ptr [ebx], ax + jmp Lcleanup +Lfloat: + fstp dword ptr [ebx] + jmp Lcleanup +Ldouble: + fstp qword ptr [ebx] + jmp Lcleanup +Lint64: + mov dword ptr [ebx], eax + mov dword ptr [ebx+4], edx + jmp Lcleanup +Lint32: + mov dword ptr [ebx], eax + jmp Lcleanup +Lcleanup: + // cleanup stack (obsolete though because of function) + mov eax, nStackLongs + shl eax, 2 // sizeof(sal_Int32) == 4 + add eax, 4 // this ptr + add esp, eax + } +} + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw () +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack + = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + + // stack space + + OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + ::uno_copyAndConvertData( + pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + ::uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + ::uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + __try + { + // pCppI is msci this pointer + callVirtualMethod( + reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset, + aVtableSlot.index, + pCppReturn, pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, + (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + } + __except (CPPU_CURRENT_NAMESPACE::msci_filterCppException( + GetExceptionInformation(), + *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) + { + // *ppUnoExc was constructed by filter function + // temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + ::uno_destructData( + pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], + cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + // return type + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + // end here + return; + } + + // NO exception occurred + *ppUnoExc = 0; + + // reconvert temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = + ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + ::uno_destructData( + pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + ::uno_copyAndConvertData( + pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + ::uno_copyAndConvertData( + pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + ::uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + ::uno_copyAndConvertData( + pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + ::uno_destructData( + pCppReturn, pReturnTypeDescr, cpp_release ); + } + // return type + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm new file mode 100644 index 000000000000..406e78d397a1 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm @@ -0,0 +1,133 @@ +; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 44; comment-start: ";; " comment-start-skip: ";; *" -*- + +;; Version: MPL 1.1 / GPLv3+ / LGPLv3+ +;; +;; The contents of this file are subject to the Mozilla Public License Version +;; 1.1 (the "License"); you may not use this file except in compliance with +;; the License or as specified alternatively below. You may obtain a copy of +;; the License at http://www.mozilla.org/MPL/ +;; +;; Software distributed under the License is distributed on an "AS IS" basis, +;; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +;; for the specific language governing rights and limitations under the +;; License. +;; +;; The Initial Developer of the Original Code is +;; Novell, Inc. +;; Portions created by the Initial Developer are Copyright (C) 2011 +;; Novell, Inc. All Rights Reserved. +;; +;; Major Contributor(s): +;; Tor Lillqvist <tml@iki.fi> +;; Portions created by Tor Lillqvist are Copyright (C) 2011 Tor Lillqvist. All Rights Reserved. +;; +;; For minor contributions see the git repository. +;; +;; Alternatively, the contents of this file may be used under the terms of +;; either the GNU General Public License Version 3 or later (the "GPLv3+"), or +;; the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +;; in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +;; instead of those above. + +;; This is the function jumped to from the trampoline generated by +;; codeSnippet() in cpp2uno.cxx. Here we call cpp_vtable_call() which +;; then calls the actual UNO function. + +;; The code snippet generated is called from "normal" C++ code which +;; has no idea that it is calling dynamically generated code. + +;; The generated short code snippet is not covered by any function +;; table and unwind info, but that doesn't matter, as the instructions +;; in it are not really going to cause any exception. Once it jumps +;; here it is covered by a function table, and the calls further down +;; through cpp_vtable_call() can be unwound cleanly. + +;; This is in a separate file for x86-64 as MSVC doesn't have in-line +;; assembly for x64. + +;; Random web links and other documentation about low-level +;; implementation details for the C++/UNO bridge on x64 Windows kept +;; here: + +;; Caolan's "Lazy Hackers Guide To Porting" is useful: +;; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting + +;; As for details about the x64 Windows calling convention, register +;; usage, stack usage, exception handling etc, the official +;; documentation (?) on MSDN is a bit fragmented and split up into a +;; needlessly large number of short pages. But still: +;; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx + +;; Also see Raymond Chen's blog post: +;; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx + +;; This one is actually more readable: "Improving Automated Analysis +;; of Windows x64 Binaries": http://www.uninformed.org/?v=4&a=1 + +;; This one has a mass of information about different architectures +;; and compilers, and contains some details about the x64 Windows +;; calling convention in particular that Microsoft doesn't mention +;; above: +;; http://www.agner.org/optimize/calling_conventions.pdf + +;; Random interesting discussion threads: +;; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8 + +;; Ken Johnson's blog http://www.nynaeve.net/ has much interesting +;; information, for instance: +;; http://www.nynaeve.net/?p=11 + +typelib_TypeClass_FLOAT equ 10 +typelib_TypeClass_DOUBLE equ 11 + +extern cpp_vtable_call: proc + +.code + +privateSnippetExecutor proc frame + + ;; Make stack frame. Re-align RSP at 16 bytes. We need just one + ;; qword of stack for our own purposes: Where cpp_vtable_call() + ;; will store the return value of the UNO callee. But we of course + ;; must also allocate space for the functions we call (i.e., just + ;; cpp_vtable_call()) to spill their register parameters. + + sub rsp, 40 + .allocstack (40) + .endprolog + + ;; Call cpp_vtable_call() with 2 parameters: + + ;; 1 (rcx): nOffsetAndIndex (already put there in code generated by codeSnippet) + ;; 2 (rdx): pointer to where to store return value, followed by our + ;; return address (uninteresting to cpp_vtable_call()), followed + ;; by our spilled register parameters, as stored above, followed + ;; by the rest of our parameters, if any. + + lea rdx, 32[rsp] + + call cpp_vtable_call + + ;; cpp_vtable_call() returns the typelib_TypeClass type of the + ;; return value of the called UNO function + + cmp rax, typelib_TypeClass_FLOAT + je Lfloat + + cmp rax, typelib_TypeClass_DOUBLE + je Lfloat + + mov rax, qword ptr 32[rsp] + jmp Lepilogue + +Lfloat: + movsd xmm0, qword ptr 32[rsp] + +Lepilogue: + add rsp, 40 + ret +privateSnippetExecutor endp + +end + +; vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx new file mode 100644 index 000000000000..ecfd957947c4 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -0,0 +1,582 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "mscx.hxx" + +using namespace ::com::sun::star::uno; + +static inline typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTD, + typelib_TypeDescriptionReference * pReturnTypeRef, // NULL indicates void return + sal_Int32 nParams, + typelib_MethodParameter * pParams, + void ** pStack ) +{ + // Return type + typelib_TypeDescription * pReturnTD = NULL; + if ( pReturnTypeRef ) + TYPELIB_DANGER_GET( &pReturnTD, pReturnTypeRef ); + + int nFirstRealParam = 3; // Index into pStack, past return + // value, return address and 'this' + // pointer. + + void * pUnoReturn = NULL; + void * pCppReturn = NULL; // Complex return ptr: if != NULL && != pUnoReturn, reconversion need + + if ( pReturnTD ) + { + if ( bridges::cpp_uno::shared::isSimpleType( pReturnTD ) ) + { + pUnoReturn = pStack; + } + else + { + pCppReturn = pStack[nFirstRealParam++]; + + pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTD ) + ? alloca( pReturnTD->nSize ) + : pCppReturn ); // direct way + } + } + + void ** pCppIncomingParams = pStack + nFirstRealParam; + + // Unlike this method for other archs, prefer clarity to + // micro-optimization, and allocate these array separately + + // Parameters passed to the UNO function + void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams ); + + // Parameters received from C++ + void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); + + // Indexes of values this have to be converted (interface conversion C++<=>UNO) + int * pTempIndexes = + (int *)alloca( sizeof(int) * nParams ); + + // Type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTD = + (typelib_TypeDescription **)alloca( sizeof(void *) * nParams ); + + int nTempIndexes = 0; + + for ( int nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + + typelib_TypeDescription * pParamTD = NULL; + TYPELIB_DANGER_GET( &pParamTD, rParam.pTypeRef ); + + if ( !rParam.bOut && + bridges::cpp_uno::shared::isSimpleType( pParamTD ) ) + { + pCppArgs[nPos] = pUnoArgs[nPos] = pCppIncomingParams++; + + TYPELIB_DANGER_RELEASE( pParamTD ); + } + else // ptr to complex value | ref + { + void * pCppStack; + + pCppArgs[nPos] = pCppStack = *pCppIncomingParams++; + + if ( !rParam.bIn ) // Pure out + { + // UNO out is unconstructed mem + pUnoArgs[nPos] = alloca( pParamTD->nSize ); + pTempIndexes[nTempIndexes] = nPos; + // pParamTD will be released at reconversion + ppTempParamTD[nTempIndexes++] = pParamTD; + } + // + else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTD ) ) + { + ::uno_copyAndConvertData( + pUnoArgs[nPos] = alloca( pParamTD->nSize ), + pCppStack, pParamTD, + pThis->getBridge()->getCpp2Uno() ); + pTempIndexes[nTempIndexes] = nPos; // Has to be reconverted + // pParamTD will be released at reconversion + ppTempParamTD[nTempIndexes++] = pParamTD; + } + else // direct way + { + pUnoArgs[nPos] = pCppStack; + // No longer needed + TYPELIB_DANGER_RELEASE( pParamTD ); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke UNO dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if ( pUnoExc ) + { + // Destruct temporary in/inout params + while ( nTempIndexes-- ) + { + int nIndex = pTempIndexes[nTempIndexes]; + + if ( pParams[nIndex].bIn ) // Is in/inout => was constructed + { + ::uno_destructData( pUnoArgs[nIndex], ppTempParamTD[nTempIndexes], 0 ); + } + TYPELIB_DANGER_RELEASE( ppTempParamTD[nTempIndexes] ); + } + if ( pReturnTD ) + TYPELIB_DANGER_RELEASE( pReturnTD ); + + CPPU_CURRENT_NAMESPACE::mscx_raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // Has to destruct the any + + // Is here for dummy + return typelib_TypeClass_VOID; + } + else // Else, no exception occurred... + { + // Temporary params + while (nTempIndexes--) + { + int nIndex = pTempIndexes[nTempIndexes]; + typelib_TypeDescription * pParamTD = ppTempParamTD[nTempIndexes]; + + if ( pParams[nIndex].bOut ) // inout/out + { + // Convert and assign + ::uno_destructData( + pCppArgs[nIndex], pParamTD, cpp_release ); + ::uno_copyAndConvertData( + pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD, + pThis->getBridge()->getUno2Cpp() ); + } + // Destroy temp UNO param + ::uno_destructData( pUnoArgs[nIndex], pParamTD, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTD ); + } + // Return + if ( pCppReturn ) // Has complex return + { + if ( pUnoReturn != pCppReturn ) // Needs reconversion + { + ::uno_copyAndConvertData( + pCppReturn, pUnoReturn, pReturnTD, + pThis->getBridge()->getUno2Cpp() ); + // Destroy temp UNO return + ::uno_destructData( pUnoReturn, pReturnTD, 0 ); + } + // Complex return ptr is set to eax + pStack[0] = pCppReturn; + } + if ( pReturnTD ) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTD->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTD ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + +extern "C" typelib_TypeClass cpp_vtable_call( + sal_Int64 nOffsetAndIndex, + void ** pStack ) +{ + sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); + sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF); + + // pStack points to space for return value allocated by + // privateSnippetExecutor() in call.asm, after which follows our + // return address (uninteresting), then the integer or + // floating-point register parameters (spilled by + // privateSnippetExecutor()) from the call to the trampoline, + // followed by stacked parameters. The first parameter is the + // 'this' pointer. If the callee returns a large value, the + // parameter after that is actually a pointer to where the callee + // should store its return value. + + void * pThis = static_cast<char *>( pStack[2] ) - nVtableOffset; + + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis ); + + typelib_InterfaceTypeDescription * pTD = pCppI->getTypeDescr(); + + OSL_ENSURE( nFunctionIndex < pTD->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" ); + if ( nFunctionIndex >= pTD->nMapFunctionIndexToMemberIndex ) + throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal vtable index!")), + reinterpret_cast<XInterface *>( pCppI ) ); + + // Determine called method + int nMemberPos = pTD->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTD->nAllMembers, "### illegal member index!\n" ); + + TypeDescription aMemberDescr( pTD->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch ( aMemberDescr.get()->eTypeClass ) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_TypeDescriptionReference *pAttrTypeRef = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef; + + if ( pTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex ) + { + // is GET method + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef, + 0, NULL, // No params + pStack ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = pAttrTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), + NULL, // Indicates void return + 1, &aParam, + pStack ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch ( nFunctionIndex ) + { + case 1: // acquire() + pCppI->acquireProxy(); // Non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = NULL; + + // the incoming C++ parameters are: The this + // pointer, the hidden return value pointer, and + // then the actual queryInterface() only + // parameter. Thus pStack[4].. + + TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pStack[4] )->getTypeLibType() ); + + if ( pTD ) + { + XInterface * pInterface = NULL; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface) + ( pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, + pCppI->getOid().pData, + reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) ); + + if ( pInterface ) + { + // pStack[3] = hidden return value pointer + ::uno_any_construct( reinterpret_cast<uno_Any *>( pStack[3] ), + &pInterface, pTD, cpp_acquire ); + + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // Fall through! + default: + { + typelib_InterfaceMethodTypeDescription * pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() ); + + eRet = cpp2uno_call( pCppI, aMemberDescr.get(), + pMethodTD->pReturnTypeRef, + pMethodTD->nParams, + pMethodTD->pParams, + pStack ); + } + } + break; + } + default: + { + throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No member description found!")), + reinterpret_cast<XInterface *>( pCppI ) ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +int const codeSnippetSize = 48; + +extern "C" char privateSnippetExecutor; + +// This function generates the code that acts as a proxy for the UNO function to be called. +// The generated code does the following: +// - Spills register parameters on stack +// - Loads functionIndex and vtableOffset into scratch registers +// - Jumps to privateSnippetExecutor + +unsigned char * codeSnippet( + unsigned char * code, + char param_kind[4], + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset ) +{ + sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex ); + unsigned char *p = code; + + // Spill parameters + if ( param_kind[0] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + { + // mov qword ptr 8[rsp], rcx + *p++ = 0x48; *p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x08; + } + else + { + // movsd qword ptr 8[rsp], xmm0 + *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08; + } + if ( param_kind[1] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + { + // mov qword ptr 16[rsp], rdx + *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10; + } + else + { + // movsd qword ptr 16[rsp], xmm1 + *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x10; + } + if ( param_kind[2] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + { + // mov qword ptr 24[rsp], r8 + *p++ = 0x4C; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18; + } + else + { + // movsd qword ptr 24[rsp], xmm2 + *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18; + } + if ( param_kind[3] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + { + // mov qword ptr 32[rsp], r9 + *p++ = 0x4C;*p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x20; + } + else + { + // movsd qword ptr 32[rsp], xmm3 + *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x5C; *p++ = 0x24; *p++ = 0x20; + } + + // mov rcx, nOffsetAndIndex + *p++ = 0x48; *p++ = 0xB9; + *((sal_uInt64 *)p) = nOffsetAndIndex; p += 8; + + // mov r11, privateSnippetExecutor + *p++ = 0x49; *p++ = 0xBB; + *((void **)p) = &privateSnippetExecutor; p += 8; + + // jmp r11 + *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3; + + OSL_ASSERT( p < code + codeSnippetSize ); + + return code + codeSnippetSize; +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable( + void * block ) +{ + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount ) +{ + return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, + sal_Int32 slotCount ) +{ + struct Rtti { + sal_Int32 n0, n1, n2; + type_info * rtti; + Rtti(): + n0(0), n1(0), n2(0), + rtti(CPPU_CURRENT_NAMESPACE::mscx_getRTTI( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XInterface")))) + {} + }; + static Rtti rtti; + + Slot * slots = mapBlockToVtable(block); + slots[-1].fn = &rtti; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, + unsigned char * code, + typelib_InterfaceTypeDescription const * type, + sal_Int32 nFunctionOffset, + sal_Int32 functionCount, + sal_Int32 nVtableOffset ) +{ + (*slots) -= functionCount; + Slot * s = *slots; + + for (int member = 0; member < type->nMembers; ++member) { + typelib_TypeDescription * pTD = NULL; + + TYPELIB_DANGER_GET( &pTD, type->ppMembers[ member ] ); + OSL_ASSERT( pTD ); + + char param_kind[4]; + int nr = 0; + + for (int i = 0; i < 4; ++i) + param_kind[i] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + + // 'this' + ++nr; + + if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE ) + { + typelib_InterfaceAttributeTypeDescription * pIfaceAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); + + // Getter + + (s++)->fn = code; + code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset ); + if ( ! pIfaceAttrTD->bReadOnly ) + { + typelib_TypeDescription * pAttrTD = NULL; + TYPELIB_DANGER_GET( &pAttrTD, pIfaceAttrTD->pAttributeTypeRef ); + OSL_ASSERT( pAttrTD ); + + // Setter + if ( pAttrTD->eTypeClass == typelib_TypeClass_FLOAT || + pAttrTD->eTypeClass == typelib_TypeClass_DOUBLE ) + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + + TYPELIB_DANGER_RELEASE( pAttrTD ); + + (s++)->fn = code; + code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset ); + } + } + else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ) + { + typelib_InterfaceMethodTypeDescription * pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); + + typelib_TypeDescription * pReturnTD = NULL; + TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef ); + OSL_ASSERT( pReturnTD ); + + if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) ) + { + // Return value + ++nr; + } + + for (int param = 0; nr < 4 && param < pMethodTD->nParams; ++param, ++nr) + { + typelib_TypeDescription * pParamTD = NULL; + + TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[param].pTypeRef ); + OSL_ASSERT( pParamTD ); + + if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT || + pParamTD->eTypeClass == typelib_TypeClass_DOUBLE ) + param_kind[nr] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + + TYPELIB_DANGER_RELEASE( pParamTD ); + } + (s++)->fn = code; + code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset ); + + TYPELIB_DANGER_RELEASE( pReturnTD ); + } + else + OSL_ASSERT( false ); + + TYPELIB_DANGER_RELEASE( pTD ); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, + unsigned char const * ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx new file mode 100644 index 000000000000..cfbc58650f0d --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#pragma warning(push,1) // disable warnings within system headers +#include <windows.h> +#pragma warning(pop) + + +void dso_init(void); +void dso_exit(void); + + +extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved) +{ + switch(dwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + + dso_init(); + break; + + case DLL_PROCESS_DETACH: + if (!lpvReserved) + dso_exit(); + break; + } + + return TRUE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx new file mode 100644 index 000000000000..2157568ad915 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -0,0 +1,850 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// Interesting info can be found in: + +// MSDN, obviously + +// http://www.osronline.com/article.cfm?article=469 + +// ONTL, "Open NT Native Template Library", a C++ STL-like library +// that can be used even when writing Windows drivers. This is some +// quite badass code. The author has done impressive heavy spelunking +// of MSVCR structures. http://code.google.com/p/ontl/ + +// Geoff Chappell's pages: +// http://members.ozemail.com.au/~geoffch/samples/programming/msvc/language/index.html + +// The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts: + +#if 0 + +/* This information until the corresponding '#endif // 0' is covered + * by ONTL's license, which is said to be the "zlib/libgng license" + * below, which as far as I see is permissive enough to allow this + * information to be included here in this source file. Note that no + * actual code from ONTL below gets compiled into the object file. + */ + +/* + * Copyright (c) 2011 <copyright holders> (The ONTL main + * developer(s) don't tell their real name(s) on the ONTL site.) + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +typedef uint32_t rva_t; + +///\note the calling convention should not matter since this has no arguments +typedef void generic_function_t(); + +struct ptrtomember // _PMD +{ + typedef __w64 int32_t mdiff_t; + mdiff_t member_offset; + mdiff_t vbtable_offset; // -1 if not a virtual base + mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable + + template<typename T> + T * operator()(T * const thisptr) const + { + uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr); + uintptr_t ptr = tp + member_offset; + if ( vbtable_offset != -1 ) // !(vbtable_offset < 0) + { + ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) ) + + vbtable_offset; + } + return reinterpret_cast<T*>(ptr); + } +}; + +struct eobject +{ + typedef void (* dtor_ptr )(eobject*); + typedef void (* ctor_ptr )(eobject*, eobject*); + typedef void (* ctor_ptr2)(eobject*, eobject*, int); +}; + +struct catchabletype +{ + /** is simple type */ + uint32_t memmoveable : 1; + /** catchable as reference only */ + uint32_t refonly : 1; + /** class with virtual base */ + uint32_t hasvirtbase : 1; + /** offset to the type descriptor */ + rva_t typeinfo; + + /** catch type instance location within a thrown object */ + ptrtomember thiscast; + /** size of the simple type or offset into buffer of \c this pointer for catch object */ + uint32_t object_size; + + union + { + rva_t copyctor; + rva_t copyctor2; + }; +}; + +#pragma pack(push, 4) +struct catchabletypearray +{ + uint32_t size; + rva_t type[1]; +}; +#pragma pack(pop) + +#pragma pack(push, 4) +struct throwinfo +{ + typedef exception_disposition __cdecl forwardcompathandler_t(...); + + /* 0x00 */ uint32_t econst : 1; + /* 0x00 */ uint32_t evolatile : 1; + /* 0x00 */ uint32_t : 1; + /* 0x00 */ uint32_t e8 : 1; + /* 0x04 */ rva_t exception_dtor; + /* 0x08 */ rva_t forwardcompathandler; + /* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception. +}; +#pragma pack(pop) + +/// This type represents the catch clause +struct ehandler +{ + // union { uint32_t adjectives; void * ptr; }; + uint32_t isconst : 1; + uint32_t isvolatile : 1; + uint32_t isunaligned : 1;// guess it is not used on x86 + uint32_t isreference : 1; + + uint32_t :27; + uint32_t ishz : 1; + + /** offset to the type descriptor of this catch object */ + /*0x04*/ rva_t typeinfo; // dispType + /*0x08*/ int eobject_bpoffset; // dispCatchObj + /** offset to the catch clause funclet */ + /*0x0C*/ rva_t handler; // dispOfHandler + /*0x10*/ uint32_t frame; // dispFrame +} + +// ___BuildCatchObject +/// 15.3/16 When the exception-declaration specifies a class type, a copy +/// constructor is used to initialize either the object declared +/// in the exception-declaration or, +/// if the exception-declaration does not specify a name, +/// a temporary object of that type. +///\note This is the question may we optimize out the last case. +///\warning If the copy constructor throws an exception, std::unexpected would be called +void + constructcatchobject( + cxxregistration * cxxreg, + const ehandler * const catchblock, + catchabletype * const convertable, + const dispatcher_context* const dispatch + ) + const +{ + _EH_TRACE_ENTER(); + // build helper + __try { + struct typeinfo_t { void* vtbl; void* spare; char name[1]; }; + enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault; + + const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL; + if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){ + eobject** objplace = catchblock->ishz + ? reinterpret_cast<eobject**>(cxxreg) + : reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers); + if(catchblock->isreference){ + // just ref/pointer + *objplace = adjust_pointer(get_object(), convertable); + }else if(convertable->memmoveable){ + // POD + std::memcpy(objplace, get_object(), convertable->object_size); + if(convertable->object_size == sizeof(void*) && *objplace) + *objplace = adjust_pointer((void*)*objplace, convertable); + }else{ + // if copy ctor exists, call it; binary copy otherwise + if(convertable->copyctor){ + cinfo = convertable->hasvirtbase ? civirtual : cicomplex; + }else{ + std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size); + } + } + } + // end of build helper + if(cinfo != cidefault){ + eobject* objthis = catchblock->ishz + ? reinterpret_cast<eobject*>(cxxreg) + : reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers); + void* copyctor = thrown_va(convertable->copyctor); + eobject* copyarg = adjust_pointer(get_object(), convertable); + if(cinfo == cicomplex) + (eobject::ctor_ptr (copyctor))(objthis, copyarg); + else + (eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1); + } + } + __except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code()))) + { + nt::exception::inconsistency(); + } + _EH_TRACE_LEAVE(); +} + +#endif // 0 + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#pragma warning( disable : 4237 ) +#include <boost/unordered_map.hpp> +#include <sal/config.h> +#include <malloc.h> +#include <new.h> +#include <typeinfo.h> +#include <signal.h> + +#include "rtl/alloc.h" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/uno/Any.hxx" + +#include "mscx.hxx" + +#pragma pack(push, 8) + +using namespace ::com::sun::star::uno; +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + +namespace CPPU_CURRENT_NAMESPACE +{ + +static inline OUString toUNOname( + OUString const & rRTTIname ) + throw () +{ + OUStringBuffer aRet( 64 ); + OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ + sal_Int32 nPos = aStr.getLength(); + while (nPos > 0) + { + sal_Int32 n = aStr.lastIndexOf( '@', nPos ); + aRet.append( aStr.copy( n +1, nPos -n -1 ) ); + if (n >= 0) + { + aRet.append( (sal_Unicode)'.' ); + } + nPos = n; + } + return aRet.makeStringAndClear(); +} + +static inline OUString toRTTIname( + OUString const & rUNOname ) + throw () +{ + OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU" + sal_Int32 nPos = rUNOname.getLength(); + while (nPos > 0) + { + sal_Int32 n = rUNOname.lastIndexOf( '.', nPos ); + aRet.append( rUNOname.copy( n +1, nPos -n -1 ) ); + aRet.append( (sal_Unicode)'@' ); + nPos = n; + } + aRet.append( (sal_Unicode)'@' ); + return aRet.makeStringAndClear(); +} + +//RTTI simulation + +typedef boost::unordered_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap; + +class RTTInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRTTI; + + static OUString toRawName( OUString const & rUNOname ) throw (); +public: + type_info * getRTTI( OUString const & rUNOname ) throw (); + + RTTInfos(); + ~RTTInfos(); +}; + +class __type_info +{ + friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); + friend int mscx_filterCppException( + LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * ); + +public: + virtual ~__type_info() throw (); + + inline __type_info( void * m_data, const char * m_d_name ) throw () + : _m_data( m_data ) + { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked + +private: + void * _m_data; + char _m_d_name[1]; +}; + +__type_info::~__type_info() throw () +{ +} + +type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () +{ + // a must be + OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" ); + + MutexGuard aGuard( _aMutex ); + t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) ); + + // check if type is already available + if (iFind == _allRTTI.end()) + { + // insert new type_info + OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) ); + __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) ) + __type_info( NULL, aRawName.getStr() ); + + // put into map + pair< t_string2PtrMap::iterator, bool > insertion( + _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) ); + OSL_ENSURE( insertion.second, "### rtti insertion failed?!" ); + + return (type_info *)pRTTI; + } + else + { + return (type_info *)iFind->second; + } +} + +RTTInfos::RTTInfos() throw () +{ +} + +RTTInfos::~RTTInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing generated RTTI infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() ); + iPos != _allRTTI.end(); ++iPos ) + { + __type_info * pType = (__type_info *)iPos->second; + pType->~__type_info(); // obsolete, but good style... + ::rtl_freeMemory( pType ); + } +} + +void * __cdecl copyConstruct( + void * pExcThis, + void * pSource, + typelib_TypeDescription * pTD ) throw () +{ + ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire ); + return pExcThis; +} + +void * __cdecl destruct( + void * pExcThis, + typelib_TypeDescription * pTD ) throw () +{ + ::uno_destructData( pExcThis, pTD, cpp_release ); + return pExcThis; +} + +const int codeSnippetSize = 40; + +void GenerateConstructorTrampoline( + unsigned char * code, + typelib_TypeDescription * pTD ) throw () +{ + unsigned char *p = code; + + // mov r8, pTD + *p++ = 0x49; *p++ = 0xB8; + *((void **)p) = pTD; p += 8; + + // mov r11, copyConstruct + *p++ = 0x49; *p++ = 0xBB; + *((void **)p) = ©Construct; p += 8; + + // jmp r11 + *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3; + + OSL_ASSERT( p < code + codeSnippetSize ); +} + +void GenerateDestructorTrampoline( + unsigned char * code, + typelib_TypeDescription * pTD ) throw () +{ + unsigned char *p = code; + + // mov rdx, pTD + *p++ = 0x48; *p++ = 0xBA; + *((void **)p) = pTD; p += 8; + + // mov r11, destruct + *p++ = 0x49; *p++ = 0xBB; + *((void **)p) = &destruct; p += 8; + + // jmp r11 + *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3; + + OSL_ASSERT( p < code + codeSnippetSize ); +} + +// This looks like it is the struct catchabletype above + +struct ExceptionType +{ + sal_Int32 _n0; // flags + sal_uInt32 _pTypeInfo; // typeinfo + sal_Int32 _n1, _n2, _n3; // thiscast + sal_Int32 _n4; // object_size + sal_uInt32 _pCopyCtor; // copyctor + + inline ExceptionType( + sal_uChar * pCode, + sal_uInt64 pCodeBase, + typelib_TypeDescription * pTD ) throw () + : _n0( 0 ) + , _n1( 0 ) + , _n2( -1 ) + , _n3( 0 ) + , _n4( pTD->nSize ) + { + // As _n0 is always initialized to zero, that means the + // hasvirtbase flag (see the ONTL catchabletype struct) is + // off, and thus the copyctor is of the ctor_ptr kind. + _pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase); + GenerateConstructorTrampoline( pCode, pTD ); + _pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase); + } + inline ~ExceptionType() throw () + { + } +}; + +struct RaiseInfo; + +class ExceptionInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRaiseInfos; + +public: + static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw (); + + static DWORD allocationGranularity; + + ExceptionInfos() throw (); + ~ExceptionInfos() throw (); +}; + +DWORD ExceptionInfos::allocationGranularity = 0; + +// This corresponds to the struct throwinfo described above. + +struct RaiseInfo +{ + sal_Int32 _n0; + sal_uInt32 _pDtor; + sal_Int32 _n2; + sal_uInt32 _types; + + // Additional fields + typelib_TypeDescription * _pTD; + sal_uChar * _code; + sal_uInt64 _codeBase; + + RaiseInfo( typelib_TypeDescription * pTD ) throw (); + + ~RaiseInfo() throw (); +}; + +RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw () + : _n0( 0 ) + , _n2( 0 ) + , _pTD( pTD ) +{ + typelib_CompoundTypeDescription * pCompTD; + + // Count how many trampolines we need + int codeSize = codeSnippetSize; + + // Info count + int nLen = 0; + for ( pCompTD = (typelib_CompoundTypeDescription*)pTD; + pCompTD; pCompTD = pCompTD->pBaseTypeDescription ) + { + ++nLen; + codeSize += codeSnippetSize; + } + + sal_uChar * pCode = _code = (sal_uChar *)::rtl_allocateMemory( codeSize ); + + _codeBase = (sal_uInt64)pCode & ~(ExceptionInfos::allocationGranularity-1); + + DWORD old_protect; +#if OSL_DEBUG_LEVEL > 0 + BOOL success = +#endif + VirtualProtect( pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect ); + OSL_ENSURE( success, "VirtualProtect() failed!" ); + + ::typelib_typedescription_acquire( pTD ); + + GenerateDestructorTrampoline( pCode, pTD ); + _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase); + pCode += codeSnippetSize; + + // Info count accompanied by type info ptrs: type, base type, base base type, ... + _types = (sal_Int32)((sal_uInt64)::rtl_allocateMemory( 4 + 4* nLen) - _codeBase); + *(sal_Int32 *)_types = nLen; + + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); + + int nPos = 0; + for ( pCompTD = (typelib_CompoundTypeDescription*)pTD; + pCompTD; pCompTD = pCompTD->pBaseTypeDescription ) + { + ppTypes[nPos++] = + new ExceptionType( pCode, _codeBase, + (typelib_TypeDescription *)pCompTD ); + pCode += codeSnippetSize; + } +} + +RaiseInfo::~RaiseInfo() throw () +{ + sal_uInt32 * pTypes = + (sal_uInt32 *)(_codeBase + _types) + 1; + + for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; ) + { + delete (ExceptionType *) (_codeBase + pTypes[nTypes]); + } + ::rtl_freeMemory( (void*)(_codeBase +_types) ); + ::rtl_freeMemory( _code ); + + ::typelib_typedescription_release( _pTD ); +} + +ExceptionInfos::ExceptionInfos() throw () +{ +} + +ExceptionInfos::~ExceptionInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing exception infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() ); + iPos != _allRaiseInfos.end(); ++iPos ) + { + delete (RaiseInfo *)iPos->second; + } +} + +RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw () +{ + static ExceptionInfos * s_pInfos = 0; + if (! s_pInfos) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pInfos) + { + SYSTEM_INFO systemInfo; + GetSystemInfo( &systemInfo ); + allocationGranularity = systemInfo.dwAllocationGranularity; + +#ifdef LEAK_STATIC_DATA + s_pInfos = new ExceptionInfos(); +#else + static ExceptionInfos s_allExceptionInfos; + s_pInfos = &s_allExceptionInfos; +#endif + } + } + + OSL_ASSERT( pTD && + (pTD->eTypeClass == typelib_TypeClass_STRUCT || + pTD->eTypeClass == typelib_TypeClass_EXCEPTION) ); + + RaiseInfo * pRaiseInfo; + + OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTD->pTypeName ); + MutexGuard aGuard( s_pInfos->_aMutex ); + t_string2PtrMap::const_iterator const iFind( + s_pInfos->_allRaiseInfos.find( rTypeName ) ); + if (iFind == s_pInfos->_allRaiseInfos.end()) + { + pRaiseInfo = new RaiseInfo( pTD ); + + // Put into map + pair< t_string2PtrMap::iterator, bool > insertion( + s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) ); + OSL_ENSURE( insertion.second, "### raise info insertion failed?!" ); + } + else + { + // Reuse existing info + pRaiseInfo = (RaiseInfo *)iFind->second; + } + + return pRaiseInfo; +} + +type_info * mscx_getRTTI( + OUString const & rUNOname ) +{ + static RTTInfos * s_pRTTIs = 0; + if (! s_pRTTIs) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pRTTIs) + { +#ifdef LEAK_STATIC_DATA + s_pRTTIs = new RTTInfos(); +#else + static RTTInfos s_aRTTIs; + s_pRTTIs = &s_aRTTIs; +#endif + } + } + return s_pRTTIs->getRTTI( rUNOname ); +} + +void mscx_raiseException( + uno_Any * pUnoExc, + uno_Mapping * pUno2Cpp ) +{ + // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()! + // thus this obj file will be compiled without opt, so no inlining of + // ExceptionInfos::getRaiseInfo() + + // construct cpp exception object + typelib_TypeDescription * pTD = NULL; + TYPELIB_DANGER_GET( &pTD, pUnoExc->pType ); + + void * pCppExc = alloca( pTD->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp ); + + ULONG_PTR arFilterArgs[4]; + arFilterArgs[0] = MSVC_magic_number; + arFilterArgs[1] = (ULONG_PTR)pCppExc; + arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD ); + arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase; + + // Destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + TYPELIB_DANGER_RELEASE( pTD ); + + // last point to release anything not affected by stack unwinding + RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); +} + +int mscx_filterCppException( + EXCEPTION_POINTERS * pPointers, + uno_Any * pUnoExc, + uno_Mapping * pCpp2Uno ) +{ + if (pPointers == 0) + return EXCEPTION_CONTINUE_SEARCH; + + EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord; + + // Handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + + bool rethrow = __CxxDetectRethrow( &pRecord ); + OSL_ASSERT( pRecord == pPointers->ExceptionRecord ); + + if (rethrow && pRecord == pPointers->ExceptionRecord) + { + // Hack to get msvcrt internal _curexception field: + pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >( + reinterpret_cast< char * >( __pxcptinfoptrs() ) + + // As long as we don't demand MSVCR source as build prerequisite, + // we have to code those offsets here. + // + // MSVS9/crt/src/mtdll.h: + // offsetof (_tiddata, _curexception) - + // offsetof (_tiddata, _tpxcptinfoptrs): +#if _MSC_VER < 1500 + error, this compiler version is not supported +#elif _MSC_VER < 1600 + 0x48 // msvcr90.dll +#else + error, please find value for this compiler version +#endif + ); + } + + // Rethrow: handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + + if (pRecord->NumberParameters == 4 && + pRecord->ExceptionInformation[0] == MSVC_magic_number && + pRecord->ExceptionInformation[1] != 0 && + pRecord->ExceptionInformation[2] != 0 && + pRecord->ExceptionInformation[3] != 0) + { + // ExceptionInformation[1] is the address of the thrown object + // (or the address of a pointer to it, in most cases when it + // is a C++ class, obviously). + + // [2] is the throwinfo pointer + + // [3] is the image base address which is added the 32-bit + // rva_t fields in throwinfo to get actual 64-bit addresses + + void * types = + (void *) (pRecord->ExceptionInformation[3] + + ((RaiseInfo *)pRecord->ExceptionInformation[2])->_types); + + if (types != 0 && *(DWORD *)types > 0) + { + DWORD pType = *((DWORD *)types + 1); + if (pType != 0 && + ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0) + { + OUString aRTTIname( + OStringToOUString( + reinterpret_cast< __type_info * >( + ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name, + RTL_TEXTENCODING_ASCII_US ) ); + OUString aUNOname( toUNOname( aRTTIname ) ); + + typelib_TypeDescription * pExcTD = 0; + typelib_typedescription_getByName( + &pExcTD, aUNOname.pData ); + if (pExcTD == NULL) + { + OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "[mscx_uno bridge error] UNO type of " + "C++ exception unknown: \"") ); + buf.append( aUNOname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\", RTTI-name=\"") ); + buf.append( aRTTIname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + RuntimeException exc( + buf.makeStringAndClear(), Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, + ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + // if (! rethrow): + // though this unknown exception leaks now, no user-defined + // exception is ever thrown thru the binary C-UNO dispatcher + // call stack. +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, (void *) pRecord->ExceptionInformation[1], + pExcTD, pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + if (! rethrow) + { + uno_destructData( + (void *) pRecord->ExceptionInformation[1], + pExcTD, cpp_release ); + } +#endif + typelib_typedescription_release( pExcTD ); + } + + return EXCEPTION_EXECUTE_HANDLER; + } + } + } + // though this unknown exception leaks now, no user-defined exception + // is ever thrown thru the binary C-UNO dispatcher call stack. + RuntimeException exc( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "[mscx_uno bridge error] unexpected " + "C++ exception occurred!") ), + Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); + return EXCEPTION_EXECUTE_HANDLER; +} + +} + +#pragma pack(pop) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk new file mode 100644 index 000000000000..7f73ebe4bba2 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=mscx_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +.IF "$(COM)$(CPU)" == "MSCX" + +.IF "$(debug)" != "" +CFLAGS += -Ob0 +.ENDIF + +.IF "$(cppu_no_leak)" == "" +.IF "$(bndchk)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF +.ENDIF + + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/dllinit.obj \ + $(SLO)$/except.obj \ + $(SLO)$/call.obj + +NOOPTFILES= \ + $(SLO)$/except.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +DEF1NAME=$(SHL1TARGET) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx new file mode 100644 index 000000000000..044bd4bb1316 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#pragma warning(push, 1) +#include <windows.h> +#pragma warning(pop) + +#include "rtl/ustring.hxx" + + +class type_info; +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +namespace CPPU_CURRENT_NAMESPACE +{ + +const DWORD MSVC_ExceptionCode = 0xe06d7363; +const long MSVC_magic_number = 0x19930520L; + +typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind; + + +//============================================================================== +type_info * mscx_getRTTI( ::rtl::OUString const & rUNOname ); + +//============================================================================== +int mscx_filterCppException( + EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); + +//============================================================================== +void mscx_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx new file mode 100644 index 000000000000..7271aa510847 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "mscx.hxx" + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +static bool cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, + typelib_MethodParameter * pParams, + void * pUnoReturn, + void * pUnoArgs[], + uno_Any ** ppUnoExc ) throw () +{ + const int MAXPARAMS = 20; + + if ( nParams > MAXPARAMS ) + { + // We have a hard limit on the number of parameters so that we + // don't need any assembler code here but can call the + // function using normal C++. + + return false; + } + + // Table with this pointer, optional complex return value ptr, and the parameters + union { + sal_Int64 i; + void *p; + double d; + } aCppParams[MAXPARAMS+2], uRetVal; + int nCppParamIndex = 0; + + // Return type + typelib_TypeDescription * pReturnTD = NULL; + TYPELIB_DANGER_GET( &pReturnTD, pReturnTypeRef ); + OSL_ENSURE( pReturnTD, "### expected return type description!" ); + + // 'this' + void * pAdjustedThisPtr = (void **)( pThis->getCppI() ) + aVtableSlot.offset; + aCppParams[nCppParamIndex++].p = pAdjustedThisPtr; + + bool bSimpleReturn = true; + if ( pReturnTD ) + { + if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) ) + { + // Complex return via ptr + bSimpleReturn = false; + aCppParams[nCppParamIndex++].p = + bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTD )? + alloca( pReturnTD->nSize ) : pUnoReturn; + } + } + + // Indexes of values this have to be converted (interface conversion C++<=>UNO) + int pTempCppIndexes[MAXPARAMS]; + int pTempIndexes[MAXPARAMS]; + int nTempIndexes = 0; + + // Type descriptions for reconversions + typelib_TypeDescription *pTempParamTypeDescr[MAXPARAMS]; + + for ( int nPos = 0; nPos < nParams; ++nPos, ++nCppParamIndex ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + + typelib_TypeDescription * pParamTD = NULL; + TYPELIB_DANGER_GET( &pParamTD, rParam.pTypeRef ); + + if ( !rParam.bOut && + bridges::cpp_uno::shared::isSimpleType( pParamTD ) ) + { + ::uno_copyAndConvertData( + &aCppParams[nCppParamIndex], pUnoArgs[nPos], pParamTD, + pThis->getBridge()->getUno2Cpp() ); + + // No longer needed + TYPELIB_DANGER_RELEASE( pParamTD ); + } + else // Ptr to complex value | ref + { + if ( !rParam.bIn ) // Is pure out + { + // C++ out is constructed mem, UNO out is not! + ::uno_constructData( + aCppParams[nCppParamIndex].p = alloca( pParamTD->nSize ), + pParamTD ); + + pTempCppIndexes[nTempIndexes] = nCppParamIndex; + pTempIndexes[nTempIndexes] = nPos; + + // Will be released at reconversion + pTempParamTypeDescr[nTempIndexes++] = pParamTD; + + } + // Is in/inout + else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTD ) ) + { + ::uno_copyAndConvertData( + aCppParams[nCppParamIndex].p = alloca( pParamTD->nSize ), + pUnoArgs[nPos], pParamTD, + pThis->getBridge()->getUno2Cpp() ); + + pTempCppIndexes[nTempIndexes] = nCppParamIndex; + pTempIndexes[nTempIndexes] = nPos; + + // Will be released at reconversion + pTempParamTypeDescr[nTempIndexes++] = pParamTD; + } + else // direct way + { + aCppParams[nCppParamIndex].p = pUnoArgs[nPos]; + + // No longer needed + TYPELIB_DANGER_RELEASE( pParamTD ); + } + } + } + + __try + { + // The first real parameter is always 'this'. + + // The Windows x64 calling convention is very regular and + // elegant (even if perhaps then slightly slower than the + // Linux x64 one): The first four parameters, never more, are + // passed in registers, as long as they are a qword in size + // or less. (If larger, a pointer to a temp copy is passed, so + // it's equivalent anyway.) Floating point values are passed + // in XMM0..3 registers, others in RCX, RDX, R8, R9. + + // Now, the nice thing for us is that when calling varargs + // functions, floating-point parameters among the four first + // ones are always passed *both* in an XMM and integer + // register. So we don't need to bother here calling the + // method different ways depending on what types of parameters + // it actually expects. We just pretend parameters 3..4 are + // doubles, and they will be passed both in XMM and integer + // registers, and the callee will find them where it + // expects. (The callee is not actually varargs, of course.) + + sal_Int64 (*pIMethod)(sal_Int64, ...) = + (sal_Int64 (*)(sal_Int64, ...)) + (*((sal_uInt64 **)pAdjustedThisPtr))[aVtableSlot.index]; + + double (*pFMethod)(sal_Int64, ...) = + (double (*)(sal_Int64, ...)) + (*((sal_uInt64 **)pAdjustedThisPtr))[aVtableSlot.index]; + + // Pass parameters 2..4 as if it was a floating-point value so + // that it gets put in both XMM and integer registers per the + // calling convention. It doesn't matter if it actually is a + // fp or not. + + if ( pReturnTD && + (pReturnTD->eTypeClass == typelib_TypeClass_FLOAT || + pReturnTD->eTypeClass == typelib_TypeClass_DOUBLE) ) + uRetVal.d = + pFMethod (aCppParams[0].i, aCppParams[1].d, aCppParams[2].d, aCppParams[3].d, + aCppParams[4].i, aCppParams[5].i, aCppParams[6].i, aCppParams[7].i, + aCppParams[8].i, aCppParams[9].i, aCppParams[10].i, aCppParams[11].i, + aCppParams[12].i, aCppParams[13].i, aCppParams[14].i, aCppParams[15].i, + aCppParams[16].i, aCppParams[17].i, aCppParams[18].i, aCppParams[19].i ); + else + uRetVal.i = + pIMethod (aCppParams[0].i, aCppParams[1].d, aCppParams[2].d, aCppParams[3].d, + aCppParams[4].i, aCppParams[5].i, aCppParams[6].i, aCppParams[7].i, + aCppParams[8].i, aCppParams[9].i, aCppParams[10].i, aCppParams[11].i, + aCppParams[12].i, aCppParams[13].i, aCppParams[14].i, aCppParams[15].i, + aCppParams[16].i, aCppParams[17].i, aCppParams[18].i, aCppParams[19].i ); + } + __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException( + GetExceptionInformation(), + *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) + { + // *ppUnoExc was constructed by filter function. + // Temporary params + while ( nTempIndexes-- ) + { + int nCppIndex = pTempCppIndexes[nTempIndexes]; + // Destroy temp C++ param => C++: every param was constructed + ::uno_destructData( + aCppParams[nCppIndex].p, pTempParamTypeDescr[nTempIndexes], + cpp_release ); + TYPELIB_DANGER_RELEASE( pTempParamTypeDescr[nTempIndexes] ); + } + // Return type + if ( pReturnTD ) + TYPELIB_DANGER_RELEASE( pReturnTD ); + + // End here + return true; + } + + // No exception occurred + *ppUnoExc = NULL; + + // Reconvert temporary params + while ( nTempIndexes-- ) + { + int nCppIndex = pTempCppIndexes[nTempIndexes]; + int nIndex = pTempIndexes[nTempIndexes]; + typelib_TypeDescription * pParamTD = + pTempParamTypeDescr[nTempIndexes]; + + if ( pParams[nIndex].bIn ) + { + if ( pParams[nIndex].bOut ) // Inout + { + ::uno_destructData( + pUnoArgs[nIndex], pParamTD, 0 ); // Destroy UNO value + ::uno_copyAndConvertData( + pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTD, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // Pure out + { + ::uno_copyAndConvertData( + pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTD, + pThis->getBridge()->getCpp2Uno() ); + } + + // Destroy temp C++ param => C++: every param was constructed + ::uno_destructData( + aCppParams[nCppIndex].p, pParamTD, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTD ); + } + + // Return value + if ( !bSimpleReturn ) + { + ::uno_copyAndConvertData( + pUnoReturn, uRetVal.p, pReturnTD, + pThis->getBridge()->getCpp2Uno() ); + ::uno_destructData( + aCppParams[1].p, pReturnTD, cpp_release ); + } + else if ( pUnoReturn ) + *(sal_Int64*)pUnoReturn = uRetVal.i; + + if ( pReturnTD ) + TYPELIB_DANGER_RELEASE( pReturnTD ); + + return true; +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, + const typelib_TypeDescription * pMemberTD, + void * pReturn, + void * pArgs[], + uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif + + switch (pMemberTD->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberTD)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberTD))); + if ( pReturn ) + { + // Is GET + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberTD)->pAttributeTypeRef, + 0, NULL, // no params + pReturn, pArgs, ppException ); + } + else + { + // Is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberTD)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = NULL; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberTD)->nPosition; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberTD))); + + switch (aVtableSlot.index) + { + // Standard calls + case 1: // Acquire UNO interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // Release UNO interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = NULL; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + + if ( pTD ) + { + uno_Interface * pInterface = NULL; + (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if ( pInterface ) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + + TYPELIB_DANGER_RELEASE( pTD ); + + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // Else perform queryInterface() + default: + if ( ! cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->pParams, + pReturn, pArgs, ppException ) ) + { + RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("Too many parameters!") ), + Reference< XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } + break; + } + default: + { + RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("Illegal member type description!") ), + Reference< XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // Binary identical null reference (whatever that comment means...) + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/bridge.cxx b/bridges/source/cpp_uno/shared/bridge.cxx new file mode 100644 index 000000000000..0b76b0ca1a8a --- /dev/null +++ b/bridges/source/cpp_uno/shared/bridge.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/bridge.hxx" + +#include "component.hxx" + +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" + +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "rtl/ustring.h" +#include "sal/types.h" +#include "typelib/typedescription.h" +#include "uno/dispatcher.h" +#include "uno/environment.h" +#include "uno/mapping.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +void freeMapping(uno_Mapping * pMapping) +{ + delete static_cast< Bridge::Mapping * >( pMapping )->pBridge; +} + +void acquireMapping(uno_Mapping * pMapping) +{ + static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire(); +} + +void releaseMapping(uno_Mapping * pMapping) +{ + static_cast< Bridge::Mapping * >( pMapping )->pBridge->release(); +} + +void cpp2unoMapping( + uno_Mapping * pMapping, void ** ppUnoI, void * pCppI, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" ); + if (*ppUnoI) + { + (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)( + reinterpret_cast< uno_Interface * >( *ppUnoI ) ); + *ppUnoI = 0; + } + if (pCppI) + { + Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; + + // get object id of interface to be wrapped + rtl_uString * pOId = 0; + (*pBridge->pCppEnv->getObjectIdentifier)( + pBridge->pCppEnv, &pOId, pCppI ); + OSL_ASSERT( pOId ); + + // try to get any known interface from target environment + (*pBridge->pUnoEnv->getRegisteredInterface)( + pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr ); + + if (! *ppUnoI) // no existing interface, register new proxy interface + { + // try to publish a new proxy (refcount initially 1) + uno_Interface * pSurrogate + = bridges::cpp_uno::shared::UnoInterfaceProxy::create( + pBridge, + static_cast< ::com::sun::star::uno::XInterface * >( pCppI ), + pTypeDescr, pOId ); + + // proxy may be exchanged during registration + (*pBridge->pUnoEnv->registerProxyInterface)( + pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ), + freeUnoInterfaceProxy, pOId, + pTypeDescr ); + + *ppUnoI = pSurrogate; + } + ::rtl_uString_release( pOId ); + } +} + +void uno2cppMapping( + uno_Mapping * pMapping, void ** ppCppI, void * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + OSL_ASSERT( ppCppI && pTypeDescr ); + if (*ppCppI) + { + static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )-> + release(); + *ppCppI = 0; + } + if (pUnoI) + { + Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; + + // get object id of uno interface to be wrapped + rtl_uString * pOId = 0; + (*pBridge->pUnoEnv->getObjectIdentifier)( + pBridge->pUnoEnv, &pOId, pUnoI ); + OSL_ASSERT( pOId ); + + // try to get any known interface from target environment + (*pBridge->pCppEnv->getRegisteredInterface)( + pBridge->pCppEnv, ppCppI, pOId, pTypeDescr ); + + if (! *ppCppI) // no existing interface, register new proxy interface + { + // try to publish a new proxy (ref count initially 1) + com::sun::star::uno::XInterface * pProxy + = bridges::cpp_uno::shared::CppInterfaceProxy::create( + pBridge, static_cast< uno_Interface * >( pUnoI ), + pTypeDescr, pOId ); + + // proxy may be exchanged during registration + (*pBridge->pCppEnv->registerProxyInterface)( + pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ), + freeCppInterfaceProxy, pOId, + pTypeDescr ); + + *ppCppI = pProxy; + } + ::rtl_uString_release( pOId ); + } +} + +uno_Mapping * Bridge::createMapping( + uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv, + bool bExportCpp2Uno) SAL_THROW(()) +{ + Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno); + return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp; +} + +void Bridge::acquire() SAL_THROW(()) +{ + if (1 == osl_incrementInterlockedCount( &nRef )) + { + if (bExportCpp2Uno) + { + uno_Mapping * pMapping = &aCpp2Uno; + ::uno_registerMapping( + &pMapping, freeMapping, (uno_Environment *)pCppEnv, + (uno_Environment *)pUnoEnv, 0 ); + } + else + { + uno_Mapping * pMapping = &aUno2Cpp; + ::uno_registerMapping( + &pMapping, freeMapping, (uno_Environment *)pUnoEnv, + (uno_Environment *)pCppEnv, 0 ); + } + } +} + +void Bridge::release() SAL_THROW(()) +{ + if (! osl_decrementInterlockedCount( &nRef )) + { + ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp ); + } +} + +Bridge::Bridge( + uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_, + bool bExportCpp2Uno_) SAL_THROW(()) + : nRef( 1 ) + , pCppEnv( pCppEnv_ ) + , pUnoEnv( pUnoEnv_ ) + , bExportCpp2Uno( bExportCpp2Uno_ ) +{ + bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire( + &bridges::cpp_uno::shared::g_moduleCount.modCnt ); + + aCpp2Uno.pBridge = this; + aCpp2Uno.acquire = acquireMapping; + aCpp2Uno.release = releaseMapping; + aCpp2Uno.mapInterface = cpp2unoMapping; + + aUno2Cpp.pBridge = this; + aUno2Cpp.acquire = acquireMapping; + aUno2Cpp.release = releaseMapping; + aUno2Cpp.mapInterface = uno2cppMapping; + + (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv ); + (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv ); +} + +Bridge::~Bridge() SAL_THROW(()) +{ + (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv ); + (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv ); + bridges::cpp_uno::shared::g_moduleCount.modCnt.release( + &bridges::cpp_uno::shared::g_moduleCount.modCnt ); +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/component.cxx b/bridges/source/cpp_uno/shared/component.cxx new file mode 100644 index 000000000000..e09370519f5a --- /dev/null +++ b/bridges/source/cpp_uno/shared/component.cxx @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "component.hxx" + +#include "bridges/cpp_uno/shared/bridge.hxx" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "osl/time.h" +#include "rtl/process.h" +#include "rtl/unload.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/environment.h" +#include "uno/lbnames.h" +#include "uno/mapping.h" +#include "cppu/EnvDcp.hxx" + +namespace bridges { namespace cpp_uno { namespace shared { + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +} } } + +namespace { + +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \ + || (defined(__GNUC__) && defined(__APPLE__)) +static ::rtl::OUString * s_pStaticOidPart = 0; +#endif + +const ::rtl::OUString & SAL_CALL cppu_cppenv_getStaticOIdPart() SAL_THROW( () ) +{ +#if ! ((defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \ + || (defined(__GNUC__) && defined(__APPLE__))) + static ::rtl::OUString * s_pStaticOidPart = 0; +#endif + if (! s_pStaticOidPart) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! s_pStaticOidPart) + { + ::rtl::OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); + // good guid + sal_uInt8 ar[16]; + ::rtl_getGlobalProcessId( ar ); + for ( sal_Int32 i = 0; i < 16; ++i ) + { + aRet.append( (sal_Int32)ar[i], 16 ); + } +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \ + || (defined(__GNUC__) && defined(__APPLE__)) + s_pStaticOidPart = new ::rtl::OUString( aRet.makeStringAndClear() ); +#else + static ::rtl::OUString s_aStaticOidPart( + aRet.makeStringAndClear() ); + s_pStaticOidPart = &s_aStaticOidPart; +#endif + } + } + return *s_pStaticOidPart; +} + +} + +extern "C" { + +static void s_stub_computeObjectIdentifier(va_list * pParam) + SAL_THROW( () ) +{ + uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); + rtl_uString ** ppOId = va_arg(*pParam, rtl_uString **); + void * pInterface = va_arg(*pParam, void *); + + + OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); + if (pEnv && ppOId && pInterface) + { + if (*ppOId) + { + rtl_uString_release( *ppOId ); + *ppOId = 0; + } + + try + { + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > xHome( + reinterpret_cast< ::com::sun::star::uno::XInterface * >( + pInterface ), + ::com::sun::star::uno::UNO_QUERY ); + OSL_ENSURE( xHome.is(), "### query to XInterface failed!" ); + if (xHome.is()) + { + // interface + ::rtl::OUStringBuffer oid( 64 ); + oid.append( reinterpret_cast< sal_Int64 >(xHome.get()), 16 ); + oid.append( (sal_Unicode)';' ); + // ;environment[context] + oid.append( + *reinterpret_cast< ::rtl::OUString const * >( + &((uno_Environment *) pEnv)->pTypeName ) ); + oid.append( (sal_Unicode)'[' ); + oid.append( + reinterpret_cast< sal_Int64 >( + ((uno_Environment *)pEnv)->pContext), + 16 ); + // ];good guid + oid.append( cppu_cppenv_getStaticOIdPart() ); + ::rtl::OUString aRet( oid.makeStringAndClear() ); + ::rtl_uString_acquire( *ppOId = aRet.pData ); + } + } + catch (::com::sun::star::uno::RuntimeException &) + { + OSL_FAIL( + "### RuntimeException occurred udring queryInterface()!" ); + } + } +} + +static void SAL_CALL computeObjectIdentifier( + uno_ExtEnvironment * pExtEnv, rtl_uString ** ppOId, void * pInterface ) + SAL_THROW( () ) +{ + uno_Environment_invoke(&pExtEnv->aBase, s_stub_computeObjectIdentifier, pExtEnv, ppOId, pInterface); +} + +static void s_stub_acquireInterface(va_list * pParam) + SAL_THROW( () ) +{ + /*uno_ExtEnvironment * pExtEnv = */va_arg(*pParam, uno_ExtEnvironment *); + void * pCppI = va_arg(*pParam, void *); + + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->acquire(); +} + +static void SAL_CALL acquireInterface( uno_ExtEnvironment * pExtEnv, void * pCppI ) + SAL_THROW( () ) +{ + uno_Environment_invoke(&pExtEnv->aBase, s_stub_acquireInterface, pExtEnv, pCppI); +} + +static void s_stub_releaseInterface(va_list * pParam) + SAL_THROW( () ) +{ + /*uno_ExtEnvironment * pExtEnv = */va_arg(*pParam, uno_ExtEnvironment *); + void * pCppI = va_arg(*pParam, void *); + + reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->release(); +} + +static void SAL_CALL releaseInterface( uno_ExtEnvironment * pExtEnv, void * pCppI ) + SAL_THROW( () ) +{ + uno_Environment_invoke(&pExtEnv->aBase, s_stub_releaseInterface, pExtEnv, pCppI); +} + +static void SAL_CALL environmentDisposing( uno_Environment * ) SAL_THROW( () ) +{ + bridges::cpp_uno::shared::g_moduleCount.modCnt.release( + &bridges::cpp_uno::shared::g_moduleCount.modCnt ); +} + +#ifndef IOS + +sal_Bool SAL_CALL component_canUnload(TimeValue * pTime) SAL_THROW_EXTERN_C() { + return bridges::cpp_uno::shared::g_moduleCount.canUnload( + &bridges::cpp_uno::shared::g_moduleCount, pTime); +} + +#endif + +#ifdef IOS +#define uno_initEnvironment gcc3_uno_initEnvironment +#endif + +void SAL_CALL uno_initEnvironment(uno_Environment * pCppEnv) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( pCppEnv->pExtEnv, "### expected extended environment!" ); + OSL_ENSURE( + ::rtl_ustr_ascii_compare_WithLength( + pCppEnv->pTypeName->buffer, rtl_str_getLength(CPPU_CURRENT_LANGUAGE_BINDING_NAME), CPPU_CURRENT_LANGUAGE_BINDING_NAME ) + == 0, + "### wrong environment type!" ); + bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire( + &bridges::cpp_uno::shared::g_moduleCount.modCnt ); + ((uno_ExtEnvironment *)pCppEnv)->computeObjectIdentifier + = computeObjectIdentifier; + ((uno_ExtEnvironment *)pCppEnv)->acquireInterface = acquireInterface; + ((uno_ExtEnvironment *)pCppEnv)->releaseInterface = releaseInterface; + pCppEnv->environmentDisposing = environmentDisposing; +} + +void SAL_CALL uno_ext_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo) + SAL_THROW_EXTERN_C() +{ + OSL_ASSERT( ppMapping && pFrom && pTo ); + if (ppMapping && pFrom && pTo && pFrom->pExtEnv && pTo->pExtEnv) + { + uno_Mapping * pMapping = 0; + + rtl::OUString from_envTypeName(cppu::EnvDcp::getTypeName(pFrom->pTypeName)); + rtl::OUString to_envTypeName(cppu::EnvDcp::getTypeName(pTo->pTypeName)); + + if (0 == rtl_ustr_ascii_compare( + from_envTypeName.pData->buffer, + CPPU_CURRENT_LANGUAGE_BINDING_NAME ) && + 0 == rtl_ustr_ascii_compare( + to_envTypeName.pData->buffer, UNO_LB_UNO )) + { + // ref count initially 1 + pMapping = bridges::cpp_uno::shared::Bridge::createMapping( + pFrom->pExtEnv, pTo->pExtEnv, sal_True ); + ::uno_registerMapping( + &pMapping, bridges::cpp_uno::shared::freeMapping, + (uno_Environment *)pFrom->pExtEnv, + (uno_Environment *)pTo->pExtEnv, 0 ); + } + else if (0 == rtl_ustr_ascii_compare( + to_envTypeName.pData->buffer, + CPPU_CURRENT_LANGUAGE_BINDING_NAME ) && + 0 == rtl_ustr_ascii_compare( + from_envTypeName.pData->buffer, UNO_LB_UNO )) + { + // ref count initially 1 + pMapping = bridges::cpp_uno::shared::Bridge::createMapping( + pTo->pExtEnv, pFrom->pExtEnv, sal_False ); + ::uno_registerMapping( + &pMapping, bridges::cpp_uno::shared::freeMapping, + (uno_Environment *)pFrom->pExtEnv, + (uno_Environment *)pTo->pExtEnv, 0 ); + } + + if (*ppMapping) + { + (*(*ppMapping)->release)( *ppMapping ); + } + if (pMapping) + *ppMapping = pMapping; + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/component.hxx b/bridges/source/cpp_uno/shared/component.hxx new file mode 100644 index 000000000000..7be6cd7a6355 --- /dev/null +++ b/bridges/source/cpp_uno/shared/component.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_COMPONENT_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_COMPONENT_HXX + +#include "rtl/unload.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +extern rtl_StandardModuleCount g_moduleCount; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx new file mode 100644 index 000000000000..5b3c8eeba37e --- /dev/null +++ b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" + +#include "guardedarray.hxx" + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/diagnose.h" +#include "osl/getglobalmutex.hxx" +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "rtl/instance.hxx" +#include "typelib/typedescription.h" + +#include <cstddef> +#include <new> + + +static bridges::cpp_uno::shared::VtableFactory * pInstance; + +#if defined(__GNUG__) && !defined(__MINGW32__) +void dso_init(void) __attribute__((constructor)); +void dso_exit(void) __attribute__((destructor)); +#endif + +void dso_init(void) { + if (!pInstance) + pInstance = new bridges::cpp_uno::shared::VtableFactory(); +} + +void dso_exit(void) { + if (pInstance) + { + delete pInstance; + pInstance = NULL; + } +} + +#ifdef __SUNPRO_CC +# pragma init(dso_init) +# pragma fini(dso_exit) +#endif + + + +namespace { + +struct InitVtableFactory { + bridges::cpp_uno::shared::VtableFactory * operator()() { + return pInstance; + } +}; + +bridges::cpp_uno::shared::VtableFactory * getVtableFactory() { + return rtl_Instance< + bridges::cpp_uno::shared::VtableFactory, InitVtableFactory, + osl::MutexGuard, osl::GetGlobalMutex >::create( + InitVtableFactory(), osl::GetGlobalMutex()); +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void freeCppInterfaceProxy(uno_ExtEnvironment * pEnv, void * pInterface) +{ + CppInterfaceProxy * pThis = CppInterfaceProxy::castInterfaceToProxy( + pInterface); + if (pEnv != pThis->pBridge->getCppEnv()) { + OSL_ASSERT(false); + } + + (*pThis->pBridge->getUnoEnv()->revokeInterface)( + pThis->pBridge->getUnoEnv(), pThis->pUnoI ); + (*pThis->pUnoI->release)( pThis->pUnoI ); + ::typelib_typedescription_release( + (typelib_TypeDescription *)pThis->pTypeDescr ); + pThis->pBridge->release(); + +#if OSL_DEBUG_LEVEL > 1 + *(int *)pInterface = 0xdeadbabe; +#endif + pThis->~CppInterfaceProxy(); + delete[] reinterpret_cast< char * >(pThis); +} + +com::sun::star::uno::XInterface * CppInterfaceProxy::create( + bridges::cpp_uno::shared::Bridge * pBridge, uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr, rtl::OUString const & rOId) + SAL_THROW(()) +{ + typelib_typedescription_complete( + reinterpret_cast< typelib_TypeDescription ** >(&pTypeDescr)); + bridges::cpp_uno::shared::VtableFactory::Vtables aVtables( + getVtableFactory()->getVtables(pTypeDescr)); + bridges::cpp_uno::shared::GuardedArray< char > pMemory( + new char[ + sizeof (CppInterfaceProxy) + + (aVtables.count - 1) * sizeof (void **)]); + new(pMemory.get()) CppInterfaceProxy(pBridge, pUnoI, pTypeDescr, rOId); + CppInterfaceProxy * pProxy = reinterpret_cast< CppInterfaceProxy * >( + pMemory.release()); + for (sal_Int32 i = 0; i < aVtables.count; ++i) { + pProxy->vtables[i] = VtableFactory::mapBlockToVtable( + aVtables.blocks[i].start); + } + return castProxyToInterface(pProxy); +} + +void CppInterfaceProxy::acquireProxy() SAL_THROW(()) +{ + if (1 == osl_incrementInterlockedCount( &nRef )) + { + // rebirth of proxy zombie + // register at cpp env + void * pThis = castProxyToInterface( this ); + (*pBridge->getCppEnv()->registerProxyInterface)( + pBridge->getCppEnv(), &pThis, freeCppInterfaceProxy, oid.pData, + pTypeDescr ); + OSL_ASSERT( pThis == castProxyToInterface( this ) ); + } +} + +void CppInterfaceProxy::releaseProxy() SAL_THROW(()) +{ + if (! osl_decrementInterlockedCount( &nRef )) // last release + { + // revoke from cpp env + (*pBridge->getCppEnv()->revokeInterface)( + pBridge->getCppEnv(), castProxyToInterface( this ) ); + } +} + +CppInterfaceProxy::CppInterfaceProxy( + bridges::cpp_uno::shared::Bridge * pBridge_, uno_Interface * pUnoI_, + typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_) + SAL_THROW(()) + : nRef( 1 ) + , pBridge( pBridge_ ) + , pUnoI( pUnoI_ ) + , pTypeDescr( pTypeDescr_ ) + , oid( rOId_ ) +{ + pBridge->acquire(); + ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); + (*pUnoI->acquire)( pUnoI ); + (*pBridge->getUnoEnv()->registerInterface)( + pBridge->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI ), oid.pData, + pTypeDescr ); +} + +CppInterfaceProxy::~CppInterfaceProxy() +{} + +com::sun::star::uno::XInterface * CppInterfaceProxy::castProxyToInterface( + CppInterfaceProxy * pProxy) +{ + return reinterpret_cast< com::sun::star::uno::XInterface * >( + &pProxy->vtables); +} + +CppInterfaceProxy * CppInterfaceProxy::castInterfaceToProxy(void * pInterface) +{ + // pInterface == &pProxy->vtables (this emulated offsetof is not truly + // portable): + char const * const base = reinterpret_cast< char const * >(16); + std::ptrdiff_t const offset = reinterpret_cast< char const * >( + &reinterpret_cast< CppInterfaceProxy const * >(base)->vtables) - base; + return reinterpret_cast< CppInterfaceProxy * >( + static_cast< char * >(pInterface) - offset); +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/guardedarray.hxx b/bridges/source/cpp_uno/shared/guardedarray.hxx new file mode 100644 index 000000000000..9e4e0f3b0cad --- /dev/null +++ b/bridges/source/cpp_uno/shared/guardedarray.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_GUARDEDARRAY_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_GUARDEDARRAY_HXX + +namespace bridges { namespace cpp_uno { namespace shared { + +template< typename T > class GuardedArray { +public: + explicit GuardedArray(T * thePointer): pointer(thePointer) {} + + ~GuardedArray() { delete[] pointer; } + + T * get() const { return pointer; } + + T * release() { T * p = pointer; pointer = 0; return p; } + +private: + GuardedArray(GuardedArray &); // not implemented + void operator =(GuardedArray); // not implemented + + T * pointer; +}; + +} } } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/makefile.mk b/bridges/source/cpp_uno/shared/makefile.mk new file mode 100644 index 000000000000..4ce8122f3261 --- /dev/null +++ b/bridges/source/cpp_uno/shared/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +PRJNAME = bridges + +TARGET = cpp_uno_shared +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk + +SLOFILES = \ + $(SLO)$/bridge.obj \ + $(SLO)$/component.obj \ + $(SLO)$/cppinterfaceproxy.obj \ + $(SLO)$/types.obj \ + $(SLO)$/unointerfaceproxy.obj \ + $(SLO)$/vtablefactory.obj \ + $(SLO)$/vtables.obj + +# Disable optimization for cppinterfaceproxy.cxx - +# attribute constructor / destructor do not get called otherwise. +.IF "$(COM)" == "GCC" +NOOPTFILES = \ + $(SLO)$/cppinterfaceproxy.obj +.ENDIF + + +.INCLUDE: target.mk diff --git a/bridges/source/cpp_uno/shared/types.cxx b/bridges/source/cpp_uno/shared/types.cxx new file mode 100644 index 000000000000..cf442082f283 --- /dev/null +++ b/bridges/source/cpp_uno/shared/types.cxx @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/types.hxx" +#define INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLES_HXX + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +bool isSimpleType(typelib_TypeClass typeClass) { + return typeClass <= typelib_TypeClass_DOUBLE + || typeClass == typelib_TypeClass_ENUM; +} + +bool isSimpleType(typelib_TypeDescriptionReference const * type) { + return isSimpleType(type->eTypeClass); +} + +bool isSimpleType(typelib_TypeDescription const * type) { + return isSimpleType(type->eTypeClass); +} + +bool relatesToInterfaceType(typelib_TypeDescription const * type) { + switch (type->eTypeClass) { + case typelib_TypeClass_ANY: + case typelib_TypeClass_INTERFACE: + return true; + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_CompoundTypeDescription const * p + = reinterpret_cast< typelib_CompoundTypeDescription const * >( + type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) { + switch (p->ppTypeRefs[i]->eTypeClass) { + case typelib_TypeClass_ANY: + case typelib_TypeClass_INTERFACE: + return true; + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_SEQUENCE: + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = relatesToInterfaceType(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + break; + + default: + break; + } + } + if (p->pBaseTypeDescription != 0) { + return relatesToInterfaceType(&p->pBaseTypeDescription->aBase); + } + } + break; + + case typelib_TypeClass_SEQUENCE: + switch (reinterpret_cast< typelib_IndirectTypeDescription const * >( + type)->pType->eTypeClass) { + case typelib_TypeClass_ANY: + case typelib_TypeClass_INTERFACE: + return true; + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_SEQUENCE: + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET( + &t, + reinterpret_cast< typelib_IndirectTypeDescription const * >( + type)->pType); + bool b = relatesToInterfaceType(t); + TYPELIB_DANGER_RELEASE(t); + return b; + } + + default: + break; + } + break; + + default: + break; + } + return false; +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx new file mode 100644 index 000000000000..e3159f12190d --- /dev/null +++ b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" + +#include "bridges/cpp_uno/shared/bridge.hxx" + +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "typelib/typedescription.h" +#include "uno/dispatcher.h" + +namespace bridges { namespace cpp_uno { namespace shared { + +void freeUnoInterfaceProxy(uno_ExtEnvironment * pEnv, void * pProxy) +{ + UnoInterfaceProxy * pThis = + static_cast< UnoInterfaceProxy * >( + reinterpret_cast< uno_Interface * >( pProxy ) ); + if (pEnv != pThis->pBridge->getUnoEnv()) { + OSL_ASSERT(false); + } + + (*pThis->pBridge->getCppEnv()->revokeInterface)( + pThis->pBridge->getCppEnv(), pThis->pCppI ); + pThis->pCppI->release(); + ::typelib_typedescription_release( + (typelib_TypeDescription *)pThis->pTypeDescr ); + pThis->pBridge->release(); + +#if OSL_DEBUG_LEVEL > 1 + *(int *)pProxy = 0xdeadbabe; +#endif + delete pThis; +} + +void acquireProxy(uno_Interface * pUnoI) +{ + if (1 == osl_incrementInterlockedCount( + & static_cast< UnoInterfaceProxy * >( pUnoI )->nRef )) + { + // rebirth of proxy zombie + // register at uno env +#if OSL_DEBUG_LEVEL > 1 + void * pThis = pUnoI; +#endif + (*static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv()-> + registerProxyInterface)( + static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv(), + reinterpret_cast< void ** >( &pUnoI ), freeUnoInterfaceProxy, + static_cast< UnoInterfaceProxy * >( pUnoI )->oid.pData, + static_cast< UnoInterfaceProxy * >( pUnoI )->pTypeDescr ); +#if OSL_DEBUG_LEVEL > 1 + OSL_ASSERT( pThis == pUnoI ); +#endif + } +} + +void releaseProxy(uno_Interface * pUnoI) +{ + if (! osl_decrementInterlockedCount( + & static_cast< UnoInterfaceProxy * >( pUnoI )->nRef )) + { + // revoke from uno env on last release + (*static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv()-> + revokeInterface)( + static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv(), + pUnoI ); + } +} + +UnoInterfaceProxy * UnoInterfaceProxy::create( + bridges::cpp_uno::shared::Bridge * pBridge, + com::sun::star::uno::XInterface * pCppI, + typelib_InterfaceTypeDescription * pTypeDescr, + rtl::OUString const & rOId) SAL_THROW(()) +{ + return new UnoInterfaceProxy(pBridge, pCppI, pTypeDescr, rOId); +} + +UnoInterfaceProxy::UnoInterfaceProxy( + bridges::cpp_uno::shared::Bridge * pBridge_, + com::sun::star::uno::XInterface * pCppI_, + typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_) + SAL_THROW(()) + : nRef( 1 ) + , pBridge( pBridge_ ) + , pCppI( pCppI_ ) + , pTypeDescr( pTypeDescr_ ) + , oid( rOId_ ) +{ + pBridge->acquire(); + ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); + if (! ((typelib_TypeDescription *)pTypeDescr)->bComplete) + ::typelib_typedescription_complete( + (typelib_TypeDescription **)&pTypeDescr ); + OSL_ENSURE( + ((typelib_TypeDescription *)pTypeDescr)->bComplete, + "### type is incomplete!" ); + pCppI->acquire(); + (*pBridge->getCppEnv()->registerInterface)( + pBridge->getCppEnv(), reinterpret_cast< void ** >( &pCppI ), oid.pData, + pTypeDescr ); + + // uno_Interface + acquire = acquireProxy; + release = releaseProxy; + pDispatcher = unoInterfaceProxyDispatch; +} + +UnoInterfaceProxy::~UnoInterfaceProxy() +{} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx new file mode 100644 index 000000000000..5d5609825a83 --- /dev/null +++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "guardedarray.hxx" + +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "osl/thread.h" +#include "osl/security.hxx" +#include "osl/file.hxx" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/alloc.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "typelib/typedescription.hxx" + +#include <boost/unordered_map.hpp> +#include <new> +#include <vector> + +#if defined SAL_UNX +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/mman.h> +#elif defined SAL_W32 +#define WIN32_LEAN_AND_MEAN +#ifdef _MSC_VER +#pragma warning(push,1) // disable warnings within system headers +#endif +#include <windows.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#else +#error Unsupported platform +#endif + +using bridges::cpp_uno::shared::VtableFactory; + +namespace { + +extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) { + sal_Size pagesize; +#if defined SAL_UNX +#if defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY + pagesize = getpagesize(); +#else + pagesize = sysconf(_SC_PAGESIZE); +#endif +#elif defined SAL_W32 + SYSTEM_INFO info; + GetSystemInfo(&info); + pagesize = info.dwPageSize; +#else +#error Unsupported platform +#endif + sal_Size n = (*size + (pagesize - 1)) & ~(pagesize - 1); + void * p; +#if defined SAL_UNX + p = mmap( + 0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, + 0); + if (p == MAP_FAILED) { + p = 0; + } + else if (mprotect (static_cast<char*>(p), n, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) + { + munmap (static_cast<char*>(p), n); + p = 0; + } +#elif defined SAL_W32 + p = VirtualAlloc(0, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#endif + if (p != 0) { + *size = n; + } + return p; +} + +extern "C" void SAL_CALL freeExec( + rtl_arena_type *, void * address, sal_Size size) +{ +#if defined SAL_UNX + munmap(static_cast< char * >(address), size); +#elif defined SAL_W32 + (void) size; // unused + VirtualFree(address, 0, MEM_RELEASE); +#endif +} + +} + +class VtableFactory::GuardedBlocks: public std::vector< Block > { +public: + GuardedBlocks(VtableFactory const & factory): + m_factory(factory), m_guarded(true) {} + + ~GuardedBlocks(); + + void unguard() { m_guarded = false; } + +private: + GuardedBlocks(GuardedBlocks &); // not implemented + void operator =(GuardedBlocks); // not implemented + + VtableFactory const & m_factory; + bool m_guarded; +}; + +VtableFactory::GuardedBlocks::~GuardedBlocks() { + if (m_guarded) { + for (iterator i(begin()); i != end(); ++i) { + m_factory.freeBlock(*i); + } + } +} + +class VtableFactory::BaseOffset { +public: + BaseOffset(typelib_InterfaceTypeDescription * type) { calculate(type, 0); } + + sal_Int32 getFunctionOffset(rtl::OUString const & name) const + { return m_map.find(name)->second; } + +private: + sal_Int32 calculate( + typelib_InterfaceTypeDescription * type, sal_Int32 offset); + + typedef boost::unordered_map< rtl::OUString, sal_Int32, rtl::OUStringHash > Map; + + Map m_map; +}; + +sal_Int32 VtableFactory::BaseOffset::calculate( + typelib_InterfaceTypeDescription * type, sal_Int32 offset) +{ + rtl::OUString name(type->aBase.pTypeName); + if (m_map.find(name) == m_map.end()) { + for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { + offset = calculate(type->ppBaseTypes[i], offset); + } + m_map.insert(Map::value_type(name, offset)); + typelib_typedescription_complete( + reinterpret_cast< typelib_TypeDescription ** >(&type)); + offset += bridges::cpp_uno::shared::getLocalFunctions(type); + } + return offset; +} + +VtableFactory::VtableFactory(): m_arena( + rtl_arena_create( + "bridges::cpp_uno::shared::VtableFactory", + sizeof (void *), // to satisfy alignment requirements + 0, reinterpret_cast< rtl_arena_type * >(-1), allocExec, freeExec, 0)) +{ + if (m_arena == 0) { + throw std::bad_alloc(); + } +} + +VtableFactory::~VtableFactory() { + { + osl::MutexGuard guard(m_mutex); + for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) { + for (sal_Int32 j = 0; j < i->second.count; ++j) { + freeBlock(i->second.blocks[j]); + } + delete[] i->second.blocks; + } + } + rtl_arena_destroy(m_arena); +} + +VtableFactory::Vtables VtableFactory::getVtables( + typelib_InterfaceTypeDescription * type) +{ + rtl::OUString name(type->aBase.pTypeName); + osl::MutexGuard guard(m_mutex); + Map::iterator i(m_map.find(name)); + if (i == m_map.end()) { + GuardedBlocks blocks(*this); + createVtables(blocks, BaseOffset(type), type, true); + Vtables vtables; + OSL_ASSERT(blocks.size() <= SAL_MAX_INT32); + vtables.count = static_cast< sal_Int32 >(blocks.size()); + bridges::cpp_uno::shared::GuardedArray< Block > guardedBlocks( + new Block[vtables.count]); + vtables.blocks = guardedBlocks.get(); + for (sal_Int32 j = 0; j < vtables.count; ++j) { + vtables.blocks[j] = blocks[j]; + } + i = m_map.insert(Map::value_type(name, vtables)).first; + guardedBlocks.release(); + blocks.unguard(); + } + return i->second; +} + +#ifdef USE_DOUBLE_MMAP +bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const +{ + sal_Size size = getBlockSize(slotCount); + sal_Size pagesize = sysconf(_SC_PAGESIZE); + block.size = (size + (pagesize - 1)) & ~(pagesize - 1); + block.start = block.exec = NULL; + block.fd = -1; + + osl::Security aSecurity; + rtl::OUString strDirectory; + rtl::OUString strURLDirectory; + if (aSecurity.getHomeDir(strURLDirectory)) + osl::File::getSystemPathFromFileURL(strURLDirectory, strDirectory); + + for (int i = strDirectory.getLength() == 0 ? 1 : 0; i < 2; ++i) + { + if (!strDirectory.getLength()) + strDirectory = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/tmp" )); + + strDirectory += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/.execoooXXXXXX" )); + rtl::OString aTmpName = rtl::OUStringToOString(strDirectory, osl_getThreadTextEncoding()); + char *tmpfname = new char[aTmpName.getLength()+1]; + strncpy(tmpfname, aTmpName.getStr(), aTmpName.getLength()+1); + if ((block.fd = mkstemp(tmpfname)) == -1) + fprintf(stderr, "mkstemp(\"%s\") failed: %s\n", tmpfname, strerror(errno)); + if (block.fd == -1) + { + delete[] tmpfname; + break; + } + unlink(tmpfname); + delete[] tmpfname; + if (ftruncate(block.fd, block.size) == -1) + { + perror("truncation of executable memory area failed"); + close(block.fd); + block.fd = -1; + break; + } + block.start = mmap(NULL, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, block.fd, 0); + if (block.start== MAP_FAILED) { + block.start = 0; + } + block.exec = mmap(NULL, block.size, PROT_READ | PROT_EXEC, MAP_SHARED, block.fd, 0); + if (block.exec == MAP_FAILED) { + block.exec = 0; + } + + //All good + if (block.start && block.exec && block.fd != -1) + break; + + freeBlock(block); + + strDirectory = rtl::OUString(); + } + if (!block.start || !block.exec || block.fd == -1) + { + //Fall back to non-doublemmaped allocation + block.fd = -1; + block.start = block.exec = rtl_arena_alloc(m_arena, &block.size); + } + return (block.start != 0 && block.exec != 0); +} + +void VtableFactory::freeBlock(Block const & block) const { + //if the double-map failed we were allocated on the arena + if (block.fd == -1 && block.start == block.exec && block.start != NULL) + rtl_arena_free(m_arena, block.start, block.size); + else + { + if (block.start) munmap(block.start, block.size); + if (block.exec) munmap(block.exec, block.size); + if (block.fd != -1) close(block.fd); + } +} +#else +bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const +{ + block.size = getBlockSize(slotCount); + block.start = rtl_arena_alloc(m_arena, &block.size); + return block.start != 0; +} + +void VtableFactory::freeBlock(Block const & block) const { + rtl_arena_free(m_arena, block.start, block.size); +} +#endif + +void VtableFactory::createVtables( + GuardedBlocks & blocks, BaseOffset const & baseOffset, + typelib_InterfaceTypeDescription * type, bool includePrimary) const +{ + if (includePrimary) { + sal_Int32 slotCount + = bridges::cpp_uno::shared::getPrimaryFunctions(type); + Block block; + if (!createBlock(block, slotCount)) { + throw std::bad_alloc(); + } + try { + Slot * slots = initializeBlock(block.start, slotCount); + unsigned char * codeBegin = + reinterpret_cast< unsigned char * >(slots); + unsigned char * code = codeBegin; + sal_Int32 vtableOffset = blocks.size() * sizeof (Slot *); + for (typelib_InterfaceTypeDescription const * type2 = type; + type2 != 0; type2 = type2->pBaseTypeDescription) + { + code = addLocalFunctions( + &slots, code, +#ifdef USE_DOUBLE_MMAP + sal_IntPtr(block.exec) - sal_IntPtr(block.start), +#endif + type2, + baseOffset.getFunctionOffset(type2->aBase.pTypeName), + bridges::cpp_uno::shared::getLocalFunctions(type2), + vtableOffset); + } + flushCode(codeBegin, code); +#ifdef USE_DOUBLE_MMAP + //Finished generating block, swap writable pointer with executable + //pointer + ::std::swap(block.start, block.exec); +#endif + blocks.push_back(block); + } catch (...) { + freeBlock(block); + throw; + } + } + for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { + createVtables(blocks, baseOffset, type->ppBaseTypes[i], i != 0); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/shared/vtables.cxx b/bridges/source/cpp_uno/shared/vtables.cxx new file mode 100644 index 000000000000..40436d0224fb --- /dev/null +++ b/bridges/source/cpp_uno/shared/vtables.cxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "osl/diagnose.h" +#include "sal/types.h" +#include "typelib/typedescription.h" + +#include <algorithm> + +namespace +{ + +/** + * Calculates the number of vtables associated with an interface type. + * + * <p>Multiple-inheritance C++ classes have more than one vtable.</p> + * + * @param type a non-null pointer to an interface type description + * @return the number of vtables associated with the given interface type + */ +sal_Int32 getVtableCount(typelib_InterfaceTypeDescription const * type) { + sal_Int32 n = 0; + for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { + n += getVtableCount(type->ppBaseTypes[i]); + } + return std::max< sal_Int32 >(n, 1); +} + +/** + * Maps a local member index to a local function index. + * + * <p><em>Local</em> members/functions are those not inherited from any base + * types. The number of <em>functions</em> is potentially larger than the + * number of <em>members</em>, as each read–write attribute member counts + * as two functions.</p> + * + * @param type a non-null pointer to an interface type description + * @param localMember a local member index, relative to the given interface type + * @return the local function index corresponding to the given local member + * index, relative to the given interface type + */ +sal_Int32 mapLocalMemberToLocalFunction( + typelib_InterfaceTypeDescription * type, sal_Int32 localMember) +{ + typelib_typedescription_complete( + reinterpret_cast< typelib_TypeDescription ** >(&type)); + sal_Int32 localMemberOffset = type->nAllMembers - type->nMembers; + sal_Int32 localFunctionOffset = type->nMapFunctionIndexToMemberIndex + - bridges::cpp_uno::shared::getLocalFunctions(type); + return type->pMapMemberIndexToFunctionIndex[localMemberOffset + localMember] + - localFunctionOffset; +} + +// Since on Solaris we compile with --instances=static, getVtableSlot cannot be +// a template function, with explicit instantiates for +// T = typelib_InterfaceAttributeTypeDescription and +// T = typelib_InterfaceMethodTypeDescription in this file; hence, there are two +// overloaded versions of getVtableSlot that both delegate to this template +// function: +template< typename T > bridges::cpp_uno::shared::VtableSlot doGetVtableSlot( + T const * ifcMember) +{ + bridges::cpp_uno::shared::VtableSlot slot; + slot.offset = 0; + T * member = const_cast< T * >(ifcMember); + while (member->pBaseRef != 0) { + OSL_ASSERT(member->nIndex < member->pInterface->nBaseTypes); + for (sal_Int32 i = 0; i < member->nIndex; ++i) { + slot.offset += getVtableCount(member->pInterface->ppBaseTypes[i]); + } + typelib_TypeDescription * desc = 0; + typelib_typedescriptionreference_getDescription( + &desc, member->pBaseRef); + OSL_ASSERT( + desc != 0 && desc->eTypeClass == member->aBase.aBase.eTypeClass); + if (member != ifcMember) { + typelib_typedescription_release(&member->aBase.aBase); + } + member = reinterpret_cast< T * >(desc); + } + slot.index + = bridges::cpp_uno::shared::getPrimaryFunctions( + member->pInterface->pBaseTypeDescription) + + mapLocalMemberToLocalFunction(member->pInterface, member->nIndex); + if (member != ifcMember) { + typelib_typedescription_release(&member->aBase.aBase); + } + return slot; +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +sal_Int32 getLocalFunctions(typelib_InterfaceTypeDescription const * type) { + return type->nMembers == 0 + ? 0 + : (type->nMapFunctionIndexToMemberIndex + - type->pMapMemberIndexToFunctionIndex[ + type->nAllMembers - type->nMembers]); +} + +sal_Int32 getPrimaryFunctions(typelib_InterfaceTypeDescription * type) { + sal_Int32 n = 0; + for (; type != 0; type = type->pBaseTypeDescription) { + typelib_typedescription_complete( + reinterpret_cast< typelib_TypeDescription ** >(&type)); + n += getLocalFunctions(type); + } + return n; +} + +VtableSlot getVtableSlot( + typelib_InterfaceAttributeTypeDescription const * ifcMember) +{ + return doGetVtableSlot(ifcMember); +} + +VtableSlot getVtableSlot( + typelib_InterfaceMethodTypeDescription const * ifcMember) +{ + return doGetVtableSlot(ifcMember); +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_info_holder.java b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_info_holder.java new file mode 100644 index 000000000000..223b53a7013f --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_info_holder.java @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.bridges.jni_uno; + +import com.sun.star.lib.util.NativeLibraryLoader; + +//============================================================================== +public final class JNI_info_holder +{ + static { + NativeLibraryLoader.loadLibrary(JNI_info_holder.class.getClassLoader(), + "java_uno"); + } + + private static JNI_info_holder s_holder = new JNI_info_holder(); + + private static long s_jni_info_handle; + + //__________________________________________________________________________ + private native void finalize( long jni_info_handle ); + + //__________________________________________________________________________ + protected void finalize() + { + finalize( s_jni_info_handle ); + } +} diff --git a/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_proxy.java b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_proxy.java new file mode 100644 index 000000000000..076d568e9c91 --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_proxy.java @@ -0,0 +1,218 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.bridges.jni_uno; + +import com.sun.star.lib.util.AsynchronousFinalizer; +import com.sun.star.lib.util.NativeLibraryLoader; +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.IEnvironment; +import com.sun.star.uno.IQueryInterface; + + +//============================================================================== +public final class JNI_proxy implements java.lang.reflect.InvocationHandler +{ + static { + NativeLibraryLoader.loadLibrary(JNI_proxy.class.getClassLoader(), + "java_uno"); + } + protected static ClassLoader s_classloader = + JNI_proxy.class.getClassLoader(); + protected static Class s_InvocationHandler [] = + new Class [] { java.lang.reflect.InvocationHandler.class }; + + protected long m_bridge_handle; + protected IEnvironment m_java_env; + protected long m_receiver_handle; + protected long m_td_handle; + protected Type m_type; + protected String m_oid; + protected Class m_class; + + //__________________________________________________________________________ + public static String get_stack_trace( Throwable throwable ) + throws Throwable + { + boolean current_trace = false; + if (null == throwable) + { + throwable = new Throwable(); + current_trace = true; + } + java.io.StringWriter string_writer = + new java.io.StringWriter(); + java.io.PrintWriter print_writer = + new java.io.PrintWriter( string_writer, true ); + throwable.printStackTrace( print_writer ); + print_writer.flush(); + print_writer.close(); + string_writer.flush(); + String trace = string_writer.toString(); + if (current_trace) + { + // cut out first two lines + int n = trace.indexOf( '\n' ); + n = trace.indexOf( '\n', n +1 ); + trace = trace.substring( n +1 ); + } + return "\njava stack trace:\n" + trace; + } + + //__________________________________________________________________________ + private native void finalize( long bridge_handle ); + + //__________________________________________________________________________ + public void finalize() + { + AsynchronousFinalizer.add(new AsynchronousFinalizer.Job() { + public void run() throws Throwable { + JNI_proxy.this.finalize( m_bridge_handle ); + } + }); + } + + //__________________________________________________________________________ + private JNI_proxy( + long bridge_handle, IEnvironment java_env, + long receiver_handle, long td_handle, Type type, String oid ) + { + m_bridge_handle = bridge_handle; + m_java_env = java_env; + m_receiver_handle = receiver_handle; + m_td_handle = td_handle; + m_type = type; + m_oid = oid; + m_class = m_type.getZClass(); + } + + //__________________________________________________________________________ + public static Object create( + long bridge_handle, IEnvironment java_env, + long receiver_handle, long td_handle, Type type, String oid, + java.lang.reflect.Constructor proxy_ctor ) + throws Throwable + { + JNI_proxy handler = new JNI_proxy( + bridge_handle, java_env, receiver_handle, td_handle, type, oid ); + Object proxy = proxy_ctor.newInstance( new Object [] { handler } ); + return java_env.registerInterface( proxy, new String [] { oid }, type ); + } + + //__________________________________________________________________________ + public static java.lang.reflect.Constructor get_proxy_ctor( Class clazz ) + throws Throwable + { + Class proxy_class = java.lang.reflect.Proxy.getProxyClass( + s_classloader, + new Class [] { clazz, IQueryInterface.class, + com.sun.star.lib.uno.Proxy.class } ); + return proxy_class.getConstructor( s_InvocationHandler ); + } + + //__________________________________________________________________________ + private native Object dispatch_call( + long bridge_handle, String decl_class, String method, Object args [] ) + throws Throwable; + + // InvocationHandler impl + //__________________________________________________________________________ + public Object invoke( + Object proxy, java.lang.reflect.Method method, Object args [] ) + throws Throwable + { + Class decl_class = method.getDeclaringClass(); + String method_name = method.getName(); + + if (Object.class.equals( decl_class )) + { + if (method_name.equals( "hashCode" )) + { + // int hashCode() + return new Integer( m_oid.hashCode() ); + } + else if (method_name.equals( "equals" )) + { + // boolean equals( Object obj ) + return isSame(args[0]); + } + else if (method_name.equals( "toString" )) + { + // String toString() + return this.toString() + " [oid=" + m_oid + + ", type=" + m_type.getTypeName() + "]"; + } + } + // UNO interface call + else if (decl_class.isAssignableFrom( m_class )) + { + // dispatch interface call + return dispatch_call( + m_bridge_handle, decl_class.getName(), method_name, args ); + } + // IQueryInterface impl + else if (IQueryInterface.class.equals( decl_class )) + { + if (method_name.equals( "queryInterface" )) + { + // Object queryInterface( Type type ) + Object registered_proxy = + m_java_env.getRegisteredInterface( m_oid, (Type)args[ 0 ] ); + if (null == registered_proxy) + { + return dispatch_call( + m_bridge_handle, + "com.sun.star.uno.XInterface", method_name, args ); + } + else + { + return registered_proxy; + } + } + else if (method_name.equals( "isSame" )) + { + // boolean isSame( Object object ) + return isSame(args[0]); + } + else if (method_name.equals( "getOid" )) + { + // String getOid() + return m_oid; + } + } + + throw new com.sun.star.uno.RuntimeException( + "[jni_uno bridge error] unexpected call on proxy " + + proxy.toString() + ": " + method.toString() ); + } + + private Boolean isSame(Object obj) { + return new Boolean(obj != null + && m_oid.equals(UnoRuntime.generateOid(obj))); + } +} diff --git a/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/makefile.mk b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/makefile.mk new file mode 100644 index 000000000000..5d3eb9fea1f5 --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/..$/..$/..$/..$/..$/..$/.. + +PRJNAME=bridges +TARGET=java_uno +PACKAGE=com$/sun$/star$/bridges$/jni_uno + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES=jurt.jar ridl.jar +JAVAFILES=$(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES))) + +JAVACLASSFILES= \ + $(CLASSDIR)$/$(PACKAGE)$/JNI_proxy.class \ + $(CLASSDIR)$/$(PACKAGE)$/JNI_info_holder.class + +JARCLASSDIRS=$(PACKAGE) +JARTARGET=$(TARGET).jar +JARCOMPRESS=TRUE +JARCLASSPATH = $(JARFILES) ../../lib/ ../bin/ +CUSTOMMANIFESTFILE = manifest + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/manifest b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/manifest new file mode 100644 index 000000000000..7ad02e156d9a --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/manifest @@ -0,0 +1 @@ +Sealed: true diff --git a/bridges/source/jni_uno/java_uno.map b/bridges/source/jni_uno/java_uno.map new file mode 100644 index 000000000000..376f7ea979bb --- /dev/null +++ b/bridges/source/jni_uno/java_uno.map @@ -0,0 +1,27 @@ +UDK_3_0_0 { + global: + uno_initEnvironment; + uno_ext_getMapping; + component_canUnload; + local: + *; +}; + +UDK_3.1 { + global: + Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J; + Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call; + Java_com_sun_star_bridges_jni_1uno_JNI_1info_1holder_finalize__J; +} UDK_3_0_0; + +UDK_3.2 { + global: + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_attach; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_create; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_destroy; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_detach; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_dispose; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_enter; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_threadId; + Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_putJob; +} UDK_3.1; diff --git a/bridges/source/jni_uno/jni_base.h b/bridges/source/jni_uno/jni_base.h new file mode 100644 index 000000000000..cc23cd1b2a8f --- /dev/null +++ b/bridges/source/jni_uno/jni_base.h @@ -0,0 +1,295 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_JNI_BASE_H +#define INCLUDED_JNI_BASE_H + +#if defined (__SUNPRO_CC) || defined (__SUNPRO_C) +// workaround solaris include trouble on jumbo +#include <stdarg.h> +namespace std +{ +typedef __va_list va_list; +} +#endif +#include <memory> + +#include "jvmaccess/unovirtualmachine.hxx" +#include "jvmaccess/virtualmachine.hxx" + +#include "osl/diagnose.h" + +#include "rtl/alloc.h" +#include "rtl/ustring.hxx" + +#include "uno/environment.h" +#include "typelib/typedescription.h" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +namespace jni_uno +{ + +class JNI_info; + +//============================================================================== +struct BridgeRuntimeError +{ + ::rtl::OUString m_message; + + inline BridgeRuntimeError( ::rtl::OUString const & message ) + : m_message( message ) + {} +}; + + +//============================================================================== +class JNI_context +{ + JNI_info const * m_jni_info; + JNIEnv * m_env; + jobject m_class_loader; + + JNI_context( JNI_context & ); // not impl + void operator = ( JNI_context ); // not impl + + void java_exc_occurred() const; +public: + inline explicit JNI_context( + JNI_info const * jni_info, JNIEnv * env, jobject class_loader ) + : m_jni_info( jni_info ), + m_env( env ), + m_class_loader( class_loader ) + {} + + inline JNI_info const * get_info() const + { return m_jni_info; } + + inline JNIEnv * operator -> () const + { return m_env; } + inline JNIEnv * get_jni_env() const + { return m_env; } + + // does not handle exceptions, *classClass will be null if exception + // occurred: + void getClassForName(jclass * classClass, jmethodID * methodForName) const; + + // if inException, does not handle exceptions, in which case returned value + // will be null if exception occurred: + jclass findClass( + char const * name, jclass classClass, jmethodID methodForName, + bool inException) const; + + inline void ensure_no_exception() const; // throws BridgeRuntimeError + inline bool assert_no_exception() const; // asserts and clears exception + + ::rtl::OUString get_stack_trace( jobject jo_exc = 0 ) const; +}; + +//______________________________________________________________________________ +inline void JNI_context::ensure_no_exception() const +{ + if (JNI_FALSE != m_env->ExceptionCheck()) + { + java_exc_occurred(); + } +} + +//______________________________________________________________________________ +inline bool JNI_context::assert_no_exception() const +{ + if (JNI_FALSE != m_env->ExceptionCheck()) + { + m_env->ExceptionClear(); + OSL_FAIL( "unexpected java exception occurred!" ); + return false; + } + return true; +} + + +//============================================================================== +class JNI_guarded_context + : private ::jvmaccess::VirtualMachine::AttachGuard, + public JNI_context +{ + JNI_guarded_context( JNI_guarded_context & ); // not impl + void operator = ( JNI_guarded_context ); // not impl + +public: + inline explicit JNI_guarded_context( + JNI_info const * jni_info, ::jvmaccess::UnoVirtualMachine * vm_access ) + : AttachGuard( vm_access->getVirtualMachine() ), + JNI_context( + jni_info, AttachGuard::getEnvironment(), + static_cast< jobject >(vm_access->getClassLoader()) ) + {} +}; + + +//============================================================================== +class JLocalAutoRef +{ + JNI_context const & m_jni; + jobject m_jo; + +public: + inline JLocalAutoRef( JNI_context const & jni ) + : m_jni( jni ), + m_jo( 0 ) + {} + inline explicit JLocalAutoRef( JNI_context const & jni, jobject jo ) + : m_jni( jni ), + m_jo( jo ) + {} + inline JLocalAutoRef( JLocalAutoRef & auto_ref ); + inline ~JLocalAutoRef() SAL_THROW( () ); + + inline jobject get() const + { return m_jo; } + inline bool is() const + { return (0 != m_jo); } + inline jobject release(); + inline void reset(); + inline void reset( jobject jo ); + inline JLocalAutoRef & operator = ( JLocalAutoRef & auto_ref ); +}; + +//______________________________________________________________________________ +inline JLocalAutoRef::~JLocalAutoRef() SAL_THROW( () ) +{ + if (0 != m_jo) + m_jni->DeleteLocalRef( m_jo ); +} + +//______________________________________________________________________________ +inline JLocalAutoRef::JLocalAutoRef( JLocalAutoRef & auto_ref ) + : m_jni( auto_ref.m_jni ), + m_jo( auto_ref.m_jo ) +{ + auto_ref.m_jo = 0; +} + +//______________________________________________________________________________ +inline jobject JLocalAutoRef::release() +{ + jobject jo = m_jo; + m_jo = 0; + return jo; +} + +//______________________________________________________________________________ +inline void JLocalAutoRef::reset() +{ + if (0 != m_jo) + m_jni->DeleteLocalRef( m_jo ); + m_jo = 0; +} + +//______________________________________________________________________________ +inline void JLocalAutoRef::reset( jobject jo ) +{ + if (jo != m_jo) + { + if (0 != m_jo) + m_jni->DeleteLocalRef( m_jo ); + m_jo = jo; + } +} + +//______________________________________________________________________________ +inline JLocalAutoRef & JLocalAutoRef::operator = ( JLocalAutoRef & auto_ref ) +{ + OSL_ASSERT( m_jni.get_jni_env() == auto_ref.m_jni.get_jni_env() ); + reset( auto_ref.m_jo ); + auto_ref.m_jo = 0; + return *this; +} + + +//============================================================================== +struct rtl_mem +{ + inline static void * operator new ( size_t nSize ) + { return rtl_allocateMemory( nSize ); } + inline static void operator delete ( void * mem ) + { if (mem) rtl_freeMemory( mem ); } + inline static void * operator new ( size_t, void * mem ) + { return mem; } + inline static void operator delete ( void *, void * ) + {} + + static inline ::std::auto_ptr< rtl_mem > allocate( ::std::size_t bytes ); +}; + +//______________________________________________________________________________ +inline ::std::auto_ptr< rtl_mem > rtl_mem::allocate( ::std::size_t bytes ) +{ + void * p = rtl_allocateMemory( bytes ); + if (0 == p) + throw BridgeRuntimeError( OUSTR("out of memory!") ); + return ::std::auto_ptr< rtl_mem >( (rtl_mem *)p ); +} + + +//============================================================================== +class TypeDescr +{ + typelib_TypeDescription * m_td; + + TypeDescr( TypeDescr & ); // not impl + void operator = ( TypeDescr ); // not impl + +public: + inline explicit TypeDescr( typelib_TypeDescriptionReference * td_ref ); + inline ~TypeDescr() SAL_THROW( () ) + { TYPELIB_DANGER_RELEASE( m_td ); } + + inline typelib_TypeDescription * get() const + { return m_td; } +}; + +//______________________________________________________________________________ +inline TypeDescr::TypeDescr( typelib_TypeDescriptionReference * td_ref ) + : m_td( 0 ) +{ + TYPELIB_DANGER_GET( &m_td, td_ref ); + if (0 == m_td) + { + throw BridgeRuntimeError( + OUSTR("cannot get comprehensive type description for ") + + ::rtl::OUString::unacquired( &td_ref->pTypeName ) ); + } +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_bridge.cxx b/bridges/source/jni_uno/jni_bridge.cxx new file mode 100644 index 000000000000..d15f05a814fd --- /dev/null +++ b/bridges/source/jni_uno/jni_bridge.cxx @@ -0,0 +1,569 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "jni_bridge.h" + +#include "jvmaccess/unovirtualmachine.hxx" +#include "rtl/ref.hxx" +#include "rtl/unload.h" +#include "rtl/strbuf.hxx" +#include "uno/lbnames.h" + + +using namespace ::std; +using namespace ::rtl; +using namespace ::osl; +using namespace ::jni_uno; + +namespace +{ +extern "C" +{ + +//------------------------------------------------------------------------------ +void SAL_CALL Mapping_acquire( uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + Mapping const * that = static_cast< Mapping const * >( mapping ); + that->m_bridge->acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL Mapping_release( uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + Mapping const * that = static_cast< Mapping const * >( mapping ); + that->m_bridge->release(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL Mapping_map_to_uno( + uno_Mapping * mapping, void ** ppOut, + void * pIn, typelib_InterfaceTypeDescription * td ) + SAL_THROW_EXTERN_C() +{ + uno_Interface ** ppUnoI = (uno_Interface **)ppOut; + jobject javaI = (jobject) pIn; + + OSL_ASSERT( sizeof (void *) == sizeof (jobject) ); + OSL_ENSURE( ppUnoI && td, "### null ptr!" ); + + if (0 == javaI) + { + if (0 != *ppUnoI) + { + uno_Interface * p = *(uno_Interface **)ppUnoI; + (*p->release)( p ); + *ppUnoI = 0; + } + } + else + { + try + { + Bridge const * bridge = + static_cast< Mapping const * >( mapping )->m_bridge; + JNI_guarded_context jni( + bridge->m_jni_info, + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext ) ); + + JNI_interface_type_info const * info = + static_cast< JNI_interface_type_info const * >( + bridge->m_jni_info->get_type_info( + jni, (typelib_TypeDescription *)td ) ); + uno_Interface * pUnoI = bridge->map_to_uno( jni, javaI, info ); + if (0 != *ppUnoI) + { + uno_Interface * p = *(uno_Interface **)ppUnoI; + (*p->release)( p ); + } + *ppUnoI = pUnoI; + } + catch (BridgeRuntimeError & err) + { +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg( + OUStringToOString( + OUSTR("[jni_uno bridge error] ") + err.m_message, + RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_FAIL( + "[jni_uno bridge error] attaching current thread " + "to java failed!" ); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL Mapping_map_to_java( + uno_Mapping * mapping, void ** ppOut, + void * pIn, typelib_InterfaceTypeDescription * td ) + SAL_THROW_EXTERN_C() +{ + jobject * ppJavaI = (jobject *) ppOut; + uno_Interface * pUnoI = (uno_Interface *)pIn; + + OSL_ASSERT( sizeof (void *) == sizeof (jobject) ); + OSL_ENSURE( ppJavaI && td, "### null ptr!" ); + + try + { + if (0 == pUnoI) + { + if (0 != *ppJavaI) + { + Bridge const * bridge = + static_cast< Mapping const * >( mapping )->m_bridge; + JNI_guarded_context jni( + bridge->m_jni_info, + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext ) ); + jni->DeleteGlobalRef( *ppJavaI ); + *ppJavaI = 0; + } + } + else + { + Bridge const * bridge = + static_cast< Mapping const * >( mapping )->m_bridge; + JNI_guarded_context jni( + bridge->m_jni_info, + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext ) ); + + JNI_interface_type_info const * info = + static_cast< JNI_interface_type_info const * >( + bridge->m_jni_info->get_type_info( + jni, (typelib_TypeDescription *)td ) ); + jobject jlocal = bridge->map_to_java( jni, pUnoI, info ); + if (0 != *ppJavaI) + jni->DeleteGlobalRef( *ppJavaI ); + *ppJavaI = jni->NewGlobalRef( jlocal ); + jni->DeleteLocalRef( jlocal ); + } + } + catch (BridgeRuntimeError & err) + { +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg( + OUStringToOString( + OUSTR("[jni_uno bridge error] ") + err.m_message, + RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_FAIL( + "[jni_uno bridge error] attaching current thread to java failed!" ); + } +} + +//______________________________________________________________________________ +void SAL_CALL Bridge_free( uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + Mapping * that = static_cast< Mapping * >( mapping ); + delete that->m_bridge; +} + +} + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +} + +namespace jni_uno +{ + +//______________________________________________________________________________ +void Bridge::acquire() const SAL_THROW( () ) +{ + if (1 == osl_incrementInterlockedCount( &m_ref )) + { + if (m_registered_java2uno) + { + uno_Mapping * mapping = const_cast< Mapping * >( &m_java2uno ); + uno_registerMapping( + &mapping, Bridge_free, + m_java_env, (uno_Environment *)m_uno_env, 0 ); + } + else + { + uno_Mapping * mapping = const_cast< Mapping * >( &m_uno2java ); + uno_registerMapping( + &mapping, Bridge_free, + (uno_Environment *)m_uno_env, m_java_env, 0 ); + } + } +} + +//______________________________________________________________________________ +void Bridge::release() const SAL_THROW( () ) +{ + if (! osl_decrementInterlockedCount( &m_ref )) + { + uno_revokeMapping( + m_registered_java2uno + ? const_cast< Mapping * >( &m_java2uno ) + : const_cast< Mapping * >( &m_uno2java ) ); + } +} + +//______________________________________________________________________________ +Bridge::Bridge( + uno_Environment * java_env, uno_ExtEnvironment * uno_env, + bool registered_java2uno ) + : m_ref( 1 ), + m_uno_env( uno_env ), + m_java_env( java_env ), + m_registered_java2uno( registered_java2uno ) +{ + // bootstrapping bridge jni_info + m_jni_info = JNI_info::get_jni_info( + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + m_java_env->pContext ) ); + + OSL_ASSERT( 0 != m_java_env && 0 != m_uno_env ); + (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env ); + (*m_java_env->acquire)( m_java_env ); + + // java2uno + m_java2uno.acquire = Mapping_acquire; + m_java2uno.release = Mapping_release; + m_java2uno.mapInterface = Mapping_map_to_uno; + m_java2uno.m_bridge = this; + // uno2java + m_uno2java.acquire = Mapping_acquire; + m_uno2java.release = Mapping_release; + m_uno2java.mapInterface = Mapping_map_to_java; + m_uno2java.m_bridge = this; + + (*g_moduleCount.modCnt.acquire)( &g_moduleCount.modCnt ); +} + +//______________________________________________________________________________ +Bridge::~Bridge() SAL_THROW( () ) +{ + (*m_java_env->release)( m_java_env ); + (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env ); + + (*g_moduleCount.modCnt.release)( &g_moduleCount.modCnt ); +} + + +//______________________________________________________________________________ +void JNI_context::java_exc_occurred() const +{ + // !don't rely on JNI_info! + + JLocalAutoRef jo_exc( *this, m_env->ExceptionOccurred() ); + m_env->ExceptionClear(); + OSL_ASSERT( jo_exc.is() ); + if (! jo_exc.is()) + { + throw BridgeRuntimeError( + OUSTR("java exception occurred, but not available!?") + + get_stack_trace() ); + } + + // call toString(); don't rely on m_jni_info + jclass jo_class = m_env->FindClass( "java/lang/Object" ); + if (JNI_FALSE != m_env->ExceptionCheck()) + { + m_env->ExceptionClear(); + throw BridgeRuntimeError( + OUSTR("cannot get class java.lang.Object!") + get_stack_trace() ); + } + JLocalAutoRef jo_Object( *this, jo_class ); + // method Object.toString() + jmethodID method_Object_toString = m_env->GetMethodID( + (jclass) jo_Object.get(), "toString", "()Ljava/lang/String;" ); + if (JNI_FALSE != m_env->ExceptionCheck()) + { + m_env->ExceptionClear(); + throw BridgeRuntimeError( + OUSTR("cannot get method id of java.lang.Object.toString()!") + + get_stack_trace() ); + } + OSL_ASSERT( 0 != method_Object_toString ); + + JLocalAutoRef jo_descr( + *this, m_env->CallObjectMethodA( + jo_exc.get(), method_Object_toString, 0 ) ); + if (m_env->ExceptionCheck()) // no chance at all + { + m_env->ExceptionClear(); + throw BridgeRuntimeError( + OUSTR("error examining java exception object!") + + get_stack_trace() ); + } + + jsize len = m_env->GetStringLength( (jstring) jo_descr.get() ); + auto_ptr< rtl_mem > ustr_mem( + rtl_mem::allocate( + sizeof (rtl_uString) + (len * sizeof (sal_Unicode)) ) ); + rtl_uString * ustr = (rtl_uString *)ustr_mem.get(); + m_env->GetStringRegion( (jstring) jo_descr.get(), 0, len, ustr->buffer ); + if (m_env->ExceptionCheck()) + { + m_env->ExceptionClear(); + throw BridgeRuntimeError( + OUSTR("invalid java string object!") + get_stack_trace() ); + } + ustr->refCount = 1; + ustr->length = len; + ustr->buffer[ len ] = '\0'; + OUString message( (rtl_uString *)ustr_mem.release(), SAL_NO_ACQUIRE ); + + throw BridgeRuntimeError( message + get_stack_trace( jo_exc.get() ) ); +} + +//______________________________________________________________________________ +void JNI_context::getClassForName( + jclass * classClass, jmethodID * methodForName) const +{ + jclass c = m_env->FindClass("java/lang/Class"); + if (c != 0) { + *methodForName = m_env->GetStaticMethodID( + c, "forName", + "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + } + *classClass = c; +} + +//______________________________________________________________________________ +jclass JNI_context::findClass( + char const * name, jclass classClass, jmethodID methodForName, + bool inException) const +{ + jclass c = 0; + JLocalAutoRef s(*this, m_env->NewStringUTF(name)); + if (s.is()) { + jvalue a[3]; + a[0].l = s.get(); + a[1].z = JNI_FALSE; + a[2].l = m_class_loader; + c = static_cast< jclass >( + m_env->CallStaticObjectMethodA(classClass, methodForName, a)); + } + if (!inException) { + ensure_no_exception(); + } + return c; +} + +//______________________________________________________________________________ +OUString JNI_context::get_stack_trace( jobject jo_exc ) const +{ + JLocalAutoRef jo_JNI_proxy( + *this, + find_class( *this, "com.sun.star.bridges.jni_uno.JNI_proxy", true ) ); + if (assert_no_exception()) + { + // static method JNI_proxy.get_stack_trace() + jmethodID method = m_env->GetStaticMethodID( + (jclass) jo_JNI_proxy.get(), "get_stack_trace", + "(Ljava/lang/Throwable;)Ljava/lang/String;" ); + if (assert_no_exception() && (0 != method)) + { + jvalue arg; + arg.l = jo_exc; + JLocalAutoRef jo_stack_trace( + *this, m_env->CallStaticObjectMethodA( + (jclass) jo_JNI_proxy.get(), method, &arg ) ); + if (assert_no_exception()) + { + jsize len = + m_env->GetStringLength( (jstring) jo_stack_trace.get() ); + auto_ptr< rtl_mem > ustr_mem( + rtl_mem::allocate( + sizeof (rtl_uString) + (len * sizeof (sal_Unicode)) ) ); + rtl_uString * ustr = (rtl_uString *)ustr_mem.get(); + m_env->GetStringRegion( + (jstring) jo_stack_trace.get(), 0, len, ustr->buffer ); + if (assert_no_exception()) + { + ustr->refCount = 1; + ustr->length = len; + ustr->buffer[ len ] = '\0'; + return OUString( + (rtl_uString *)ustr_mem.release(), SAL_NO_ACQUIRE ); + } + } + } + } + return OUString(); +} + +} + +using namespace ::jni_uno; + +extern "C" +{ +namespace +{ + +//------------------------------------------------------------------------------ +void SAL_CALL java_env_disposing( uno_Environment * java_env ) + SAL_THROW_EXTERN_C() +{ + ::jvmaccess::UnoVirtualMachine * machine = + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + java_env->pContext ); + java_env->pContext = 0; + machine->release(); +} +} + +//------------------------------------------------------------------------------ +void SAL_CALL uno_initEnvironment( uno_Environment * java_env ) + SAL_THROW_EXTERN_C() +{ + java_env->environmentDisposing = java_env_disposing; + java_env->pExtEnv = 0; // no extended support + OSL_ASSERT( 0 != java_env->pContext ); + + ::jvmaccess::UnoVirtualMachine * machine = + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + java_env->pContext ); + machine->acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL uno_ext_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) + SAL_THROW_EXTERN_C() +{ + OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo ); + if (0 != *ppMapping) + { + (*(*ppMapping)->release)( *ppMapping ); + *ppMapping = 0; + } + + OSL_ASSERT( JNI_FALSE == sal_False ); + OSL_ASSERT( JNI_TRUE == sal_True ); + OSL_ASSERT( sizeof (jboolean) == sizeof (sal_Bool) ); + OSL_ASSERT( sizeof (jchar) == sizeof (sal_Unicode) ); + OSL_ASSERT( sizeof (jdouble) == sizeof (double) ); + OSL_ASSERT( sizeof (jfloat) == sizeof (float) ); + OSL_ASSERT( sizeof (jbyte) == sizeof (sal_Int8) ); + OSL_ASSERT( sizeof (jshort) == sizeof (sal_Int16) ); + OSL_ASSERT( sizeof (jint) == sizeof (sal_Int32) ); + OSL_ASSERT( sizeof (jlong) == sizeof (sal_Int64) ); + if ((JNI_FALSE == sal_False) && + (JNI_TRUE == sal_True) && + (sizeof (jboolean) == sizeof (sal_Bool)) && + (sizeof (jchar) == sizeof (sal_Unicode)) && + (sizeof (jdouble) == sizeof (double)) && + (sizeof (jfloat) == sizeof (float)) && + (sizeof (jbyte) == sizeof (sal_Int8)) && + (sizeof (jshort) == sizeof (sal_Int16)) && + (sizeof (jint) == sizeof (sal_Int32)) && + (sizeof (jlong) == sizeof (sal_Int64))) + { + OUString const & from_env_typename = + OUString::unacquired( &pFrom->pTypeName ); + OUString const & to_env_typename = + OUString::unacquired( &pTo->pTypeName ); + + uno_Mapping * mapping = 0; + + try + { + if (from_env_typename.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(UNO_LB_JAVA) ) && + to_env_typename.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) + { + Bridge * bridge = + new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1 + mapping = &bridge->m_java2uno; + uno_registerMapping( + &mapping, Bridge_free, + pFrom, (uno_Environment *)pTo->pExtEnv, 0 ); + } + else if (from_env_typename.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ) && + to_env_typename.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(UNO_LB_JAVA) )) + { + Bridge * bridge = + new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1 + mapping = &bridge->m_uno2java; + uno_registerMapping( + &mapping, Bridge_free, + (uno_Environment *)pFrom->pExtEnv, pTo, 0 ); + } + } + catch (BridgeRuntimeError & err) + { +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg( + OUStringToOString( + OUSTR("[jni_uno bridge error] ") + err.m_message, + RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_FAIL( + "[jni_uno bridge error] attaching current thread " + "to java failed!" ); + } + + *ppMapping = mapping; + } +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL component_canUnload( TimeValue * pTime ) + SAL_THROW_EXTERN_C() +{ + return (*g_moduleCount.canUnload)( &g_moduleCount, pTime ); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_bridge.h b/bridges/source/jni_uno/jni_bridge.h new file mode 100644 index 000000000000..f2298fbdbe46 --- /dev/null +++ b/bridges/source/jni_uno/jni_bridge.h @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_JNI_BRIDGE_H +#define INCLUDED_JNI_BRIDGE_H + +#include "jni_base.h" +#include "jni_info.h" +#include "jni_helper.h" + +#include "osl/diagnose.h" +#include "osl/interlck.h" + +#include "uno/mapping.h" +#include "uno/dispatcher.h" + +#include "com/sun/star/uno/XInterface.hpp" + + +namespace jni_uno +{ + +//==== holds environments and mappings ========================================= +struct Bridge; +struct Mapping : public uno_Mapping +{ + Bridge * m_bridge; +}; + +//============================================================================== +struct Bridge +{ + mutable oslInterlockedCount m_ref; + + uno_ExtEnvironment * m_uno_env; + uno_Environment * m_java_env; + + Mapping m_java2uno; + Mapping m_uno2java; + bool m_registered_java2uno; + + JNI_info const * m_jni_info; + + // + ~Bridge() SAL_THROW( () ); + explicit Bridge( + uno_Environment * java_env, uno_ExtEnvironment * uno_env, + bool registered_java2uno ); + + void acquire() const; + void release() const; + + // jni_data.cxx + void map_to_uno( + JNI_context const & jni, + void * uno_data, jvalue java_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool assign, bool out_param, + bool special_wrapped_integral_types = false ) const; + void map_to_java( + JNI_context const & jni, + jvalue * java_data, void const * uno_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool in_param, bool out_param, + bool special_wrapped_integral_types = false ) const; + + // jni_uno2java.cxx + void handle_uno_exc( + JNI_context const & jni, uno_Any * uno_exc ) const; + void call_java( + jobject javaI, + typelib_InterfaceTypeDescription * iface_td, + sal_Int32 local_member_index, sal_Int32 function_pos_offset, + typelib_TypeDescriptionReference * return_type, + typelib_MethodParameter * params, sal_Int32 nParams, + void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const; + jobject map_to_java( + JNI_context const & jni, + uno_Interface * pUnoI, JNI_interface_type_info const * info ) const; + + // jni_java2uno.cxx + void handle_java_exc( + JNI_context const & jni, + JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const; + jobject call_uno( + JNI_context const & jni, + uno_Interface * pUnoI, typelib_TypeDescription * member_td, + typelib_TypeDescriptionReference * return_tdref, + sal_Int32 nParams, typelib_MethodParameter const * pParams, + jobjectArray jo_args ) const; + uno_Interface * map_to_uno( + JNI_context const & jni, + jobject javaI, JNI_interface_type_info const * info ) const; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_data.cxx b/bridges/source/jni_uno/jni_data.cxx new file mode 100644 index 000000000000..aca455d154ed --- /dev/null +++ b/bridges/source/jni_uno/jni_data.cxx @@ -0,0 +1,2579 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "jni_bridge.h" + +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "uno/sequence2.h" + + +using namespace ::std; +using namespace ::rtl; + +namespace jni_uno +{ + +//------------------------------------------------------------------------------ +inline rtl_mem * seq_allocate( sal_Int32 nElements, sal_Int32 nSize ) +{ + auto_ptr< rtl_mem > seq( + rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) ); + uno_Sequence * p = (uno_Sequence *)seq.get(); + p->nRefCount = 1; + p->nElements = nElements; + return seq.release(); +} + +//______________________________________________________________________________ +namespace { + +void createDefaultUnoValue( + JNI_context const & jni, void * uno_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, bool assign) +{ + switch (type->eTypeClass) { + case typelib_TypeClass_BOOLEAN: + *static_cast< sal_Bool * >(uno_data) = false; + break; + + case typelib_TypeClass_BYTE: + *static_cast< sal_Int8 * >(uno_data) = 0; + break; + + case typelib_TypeClass_SHORT: + *static_cast< sal_Int16 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_SHORT: + *static_cast< sal_uInt16 * >(uno_data) = 0; + break; + + case typelib_TypeClass_LONG: + *static_cast< sal_Int32 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_LONG: + *static_cast< sal_uInt32 * >(uno_data) = 0; + break; + + case typelib_TypeClass_HYPER: + *static_cast< sal_Int64 * >(uno_data) = 0; + break; + + case typelib_TypeClass_UNSIGNED_HYPER: + *static_cast< sal_uInt64 * >(uno_data) = 0; + break; + + case typelib_TypeClass_FLOAT: + *static_cast< float * >(uno_data) = 0; + break; + + case typelib_TypeClass_DOUBLE: + *static_cast< double * >(uno_data) = 0; + break; + + case typelib_TypeClass_CHAR: + *static_cast< sal_Unicode * >(uno_data) = 0; + break; + + case typelib_TypeClass_STRING: + if (!assign) { + *static_cast< rtl_uString ** >(uno_data) = 0; + } + rtl_uString_new(static_cast< rtl_uString ** >(uno_data)); + break; + + case typelib_TypeClass_TYPE: + if (assign) { + typelib_typedescriptionreference_release( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data)); + } + *static_cast< typelib_TypeDescriptionReference ** >(uno_data) + = *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID); + OSL_ASSERT( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data) != 0); + typelib_typedescriptionreference_acquire( + *static_cast< typelib_TypeDescriptionReference ** >(uno_data)); + break; + + case typelib_TypeClass_ANY: + if (assign) { + uno_any_destruct(static_cast< uno_Any * >(uno_data), 0); + } + uno_any_construct( + static_cast< uno_Any * >(uno_data), 0, + jni.get_info()->m_XInterface_type_info->m_td.get(), 0); + break; + + case typelib_TypeClass_SEQUENCE: + { + auto_ptr< rtl_mem > seq(seq_allocate(0, 0)); + if (assign) { + uno_type_destructData(uno_data, type, 0); + } + *static_cast< uno_Sequence ** >(uno_data) + = reinterpret_cast< uno_Sequence * >(seq.release()); + break; + } + + case typelib_TypeClass_ENUM: + { + typelib_TypeDescription * td = 0; + TYPELIB_DANGER_GET(&td, type); + *static_cast< sal_Int32 * >(uno_data) + = (reinterpret_cast< typelib_EnumTypeDescription * >(td)-> + nDefaultEnumValue); + TYPELIB_DANGER_RELEASE(td); + break; + } + + case typelib_TypeClass_STRUCT: + { + if (info == 0) { + info = jni.get_info()->get_type_info(jni, type); + } + JNI_compound_type_info const * comp_info + = static_cast< JNI_compound_type_info const * >(info); + typelib_CompoundTypeDescription * comp_td + = reinterpret_cast< typelib_CompoundTypeDescription * >( + comp_info->m_td.get()); + sal_Int32 nPos = 0; + sal_Int32 nMembers = comp_td->nMembers; + try { + if (comp_td->pBaseTypeDescription != 0) { + createDefaultUnoValue( + jni, uno_data, + comp_td->pBaseTypeDescription->aBase.pWeakRef, + comp_info->m_base, assign); + } + for (; nPos < nMembers; ++nPos) { + createDefaultUnoValue( + jni, + (static_cast< char * >(uno_data) + + comp_td->pMemberOffsets[nPos]), + comp_td->ppTypeRefs[nPos], 0, assign); + } + } catch (...) { + if (!assign) { + for (sal_Int32 i = 0; i < nPos; ++i) { + uno_type_destructData( + (static_cast< char * >(uno_data) + + comp_td->pMemberOffsets[i]), + comp_td->ppTypeRefs[i], 0); + } + if (comp_td->pBaseTypeDescription != 0) { + uno_destructData( + uno_data, &comp_td->pBaseTypeDescription->aBase, 0); + } + } + throw; + } + } + break; + + case typelib_TypeClass_INTERFACE: + if (assign) { + uno_Interface * p = *static_cast< uno_Interface ** >(uno_data); + if (p != 0) { + (*p->release)(p); + } + } + *static_cast< uno_Interface ** >(uno_data) = 0; + break; + + default: + OSL_ASSERT(false); + break; + } +} + +} + +void Bridge::map_to_uno( + JNI_context const & jni, + void * uno_data, jvalue java_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool assign, bool out_param, + bool special_wrapped_integral_types ) const +{ + OSL_ASSERT( + !out_param || + (1 == jni->GetArrayLength( (jarray) java_data.l )) ); + + switch (type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (out_param) + { + jni->GetCharArrayRegion( + (jcharArray) java_data.l, 0, 1, (jchar *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jchar *) uno_data = jni->CallCharMethodA( + java_data.l, m_jni_info->m_method_Character_charValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jchar *) uno_data = java_data.c; + } + break; + case typelib_TypeClass_BOOLEAN: + if (out_param) + { + jni->GetBooleanArrayRegion( + (jbooleanArray) java_data.l, 0, 1, (jboolean *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jboolean *) uno_data = jni->CallBooleanMethodA( + java_data.l, m_jni_info->m_method_Boolean_booleanValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jboolean *) uno_data = java_data.z; + } + break; + case typelib_TypeClass_BYTE: + if (out_param) + { + jni->GetByteArrayRegion( + (jbyteArray) java_data.l, 0, 1, (jbyte *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jbyte *) uno_data = jni->CallByteMethodA( + java_data.l, m_jni_info->m_method_Byte_byteValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jbyte *) uno_data = java_data.b; + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (out_param) + { + jni->GetShortArrayRegion( + (jshortArray) java_data.l, 0, 1, (jshort *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jshort *) uno_data = jni->CallShortMethodA( + java_data.l, m_jni_info->m_method_Short_shortValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jshort *) uno_data = java_data.s; + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (out_param) + { + jni->GetIntArrayRegion( + (jintArray) java_data.l, 0, 1, (jint *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jint *) uno_data = jni->CallIntMethodA( + java_data.l, m_jni_info->m_method_Integer_intValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jint *) uno_data = java_data.i; + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (out_param) + { + jni->GetLongArrayRegion( + (jlongArray) java_data.l, 0, 1, (jlong *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jlong *) uno_data = jni->CallLongMethodA( + java_data.l, m_jni_info->m_method_Long_longValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jlong *) uno_data = java_data.j; + } + break; + case typelib_TypeClass_FLOAT: + if (out_param) + { + jni->GetFloatArrayRegion( + (jfloatArray) java_data.l, 0, 1, (jfloat *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jfloat *) uno_data = jni->CallFloatMethodA( + java_data.l, m_jni_info->m_method_Float_floatValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jfloat *) uno_data = java_data.f; + } + break; + case typelib_TypeClass_DOUBLE: + if (out_param) + { + jni->GetDoubleArrayRegion( + (jdoubleArray) java_data.l, 0, 1, (jdouble *) uno_data ); + jni.ensure_no_exception(); + } + else if (special_wrapped_integral_types) + { + *(jdouble *) uno_data = jni->CallDoubleMethodA( + java_data.l, m_jni_info->m_method_Double_doubleValue, 0 ); + jni.ensure_no_exception(); + } + else + { + *(jdouble *) uno_data = java_data.d; + } + break; + case typelib_TypeClass_STRING: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (0 == java_data.l) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] null-ref given!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + if (! assign) + *(rtl_uString **)uno_data = 0; + jstring_to_ustring( + jni, (rtl_uString **)uno_data, (jstring) java_data.l ); + break; + } + case typelib_TypeClass_TYPE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (0 == java_data.l) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] null-ref given!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + + // type name + JLocalAutoRef jo_type_name( + jni, jni->GetObjectField( + java_data.l, m_jni_info->m_field_Type__typeName ) ); + if (! jo_type_name.is()) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] incomplete type object: " + "no type name!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + OUString type_name( + jstring_to_oustring( jni, (jstring) jo_type_name.get() ) ); + ::com::sun::star::uno::TypeDescription td( type_name ); + if (! td.is()) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] UNO type not found: ") ); + buf.append( type_name ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); + if (assign) + { + typelib_typedescriptionreference_release( + *(typelib_TypeDescriptionReference **)uno_data ); + } + *(typelib_TypeDescriptionReference **)uno_data = td.get()->pWeakRef; + break; + } + case typelib_TypeClass_ANY: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + + uno_Any * pAny = (uno_Any *)uno_data; + if (0 == java_data.l) // null-ref maps to XInterface null-ref + { + if (assign) + uno_any_destruct( pAny, 0 ); + uno_any_construct( + pAny, 0, m_jni_info->m_XInterface_type_info->m_td.get(), 0 ); + break; + } + + JLocalAutoRef jo_type( jni ); + JLocalAutoRef jo_wrapped_holder( jni ); + + if (JNI_FALSE != jni->IsInstanceOf( + java_data.l, m_jni_info->m_class_Any )) + { + // boxed any + jo_type.reset( jni->GetObjectField( + java_data.l, m_jni_info->m_field_Any__type ) ); + if (! jo_type.is()) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] no type set at " + "com.sun.star.uno.Any!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + // wrapped value + jo_wrapped_holder.reset( + jni->GetObjectField( + java_data.l, m_jni_info->m_field_Any__object ) ); + java_data.l = jo_wrapped_holder.get(); + } + else + { + // create type out of class + JLocalAutoRef jo_class( jni, jni->GetObjectClass( java_data.l ) ); + jo_type.reset( create_type( jni, (jclass) jo_class.get() ) ); +#if OSL_DEBUG_LEVEL > 1 + { + JLocalAutoRef jo_toString( + jni, jni->CallObjectMethodA( + java_data.l, m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + OUString toString( + jstring_to_oustring( jni, (jstring) jo_toString.get() ) ); + } +#endif + } + + // get type name + JLocalAutoRef jo_type_name( + jni, jni->GetObjectField( + jo_type.get(), m_jni_info->m_field_Type__typeName ) ); + jni.ensure_no_exception(); + OUString type_name( + jstring_to_oustring( jni, (jstring) jo_type_name.get() ) ); + + ::com::sun::star::uno::TypeDescription value_td( type_name ); + if (! value_td.is()) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] UNO type not found: ") ); + buf.append( type_name ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + typelib_TypeClass type_class = value_td.get()->eTypeClass; + + if (assign) + { + uno_any_destruct( pAny, 0 ); + } + try + { + switch (type_class) + { + case typelib_TypeClass_VOID: + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_CHAR: + pAny->pData = &pAny->pReserved; + *(jchar *) pAny->pData = jni->CallCharMethodA( + java_data.l, m_jni_info->m_method_Character_charValue, 0 ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BOOLEAN: + pAny->pData = &pAny->pReserved; + *(jboolean *) pAny->pData = jni->CallBooleanMethodA( + java_data.l, m_jni_info->m_method_Boolean_booleanValue, 0 ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BYTE: + pAny->pData = &pAny->pReserved; + *(jbyte *) pAny->pData = jni->CallByteMethodA( + java_data.l, m_jni_info->m_method_Byte_byteValue, 0 ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pAny->pData = &pAny->pReserved; + *(jshort *) pAny->pData = jni->CallShortMethodA( + java_data.l, m_jni_info->m_method_Short_shortValue, 0 ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + pAny->pData = &pAny->pReserved; + *(jint *) pAny->pData = jni->CallIntMethodA( + java_data.l, m_jni_info->m_method_Integer_intValue, 0 ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof (sal_Int64) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *(jlong *) pAny->pData = jni->CallLongMethodA( + java_data.l, m_jni_info->m_method_Long_longValue, 0 ); + jni.ensure_no_exception(); + } + else + { + auto_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (sal_Int64) ) ); + *(jlong *) mem.get() = jni->CallLongMethodA( + java_data.l, m_jni_info->m_method_Long_longValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof (float) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *(jfloat *) pAny->pData = jni->CallFloatMethodA( + java_data.l, m_jni_info->m_method_Float_floatValue, 0 ); + jni.ensure_no_exception(); + } + else + { + auto_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (float) ) ); + *(jfloat *) mem.get() = jni->CallFloatMethodA( + java_data.l, m_jni_info->m_method_Float_floatValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof (double) <= sizeof (void *)) + { + pAny->pData = &pAny->pReserved; + *(jdouble *) pAny->pData = + jni->CallDoubleMethodA( + java_data.l, + m_jni_info->m_method_Double_doubleValue, 0 ); + jni.ensure_no_exception(); + } + else + { + auto_ptr< rtl_mem > mem( + rtl_mem::allocate( sizeof (double) ) ); + *(jdouble *) mem.get() = + jni->CallDoubleMethodA( + java_data.l, + m_jni_info->m_method_Double_doubleValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = mem.release(); + } + break; + case typelib_TypeClass_STRING: + // opt: anies often contain strings; copy string directly + pAny->pReserved = 0; + pAny->pData = &pAny->pReserved; + jstring_to_ustring( + jni, (rtl_uString **)pAny->pData, + (jstring) java_data.l ); + break; + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + pAny->pData = &pAny->pReserved; + map_to_uno( + jni, pAny->pData, java_data, + value_td.get()->pWeakRef, 0, + false /* no assign */, false /* no out param */ ); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + auto_ptr< rtl_mem > mem( + rtl_mem::allocate( value_td.get()->nSize ) ); + map_to_uno( + jni, mem.get(), java_data, value_td.get()->pWeakRef, 0, + false /* no assign */, false /* no out param */ ); + pAny->pData = mem.release(); + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( type_name ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] unsupported value type " + "of any!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } + } + catch (...) + { + if (assign) + { + // restore to valid any + uno_any_construct( pAny, 0, 0, 0 ); + } + throw; + } + typelib_typedescriptionreference_acquire( value_td.get()->pWeakRef ); + pAny->pType = value_td.get()->pWeakRef; + break; + } + case typelib_TypeClass_ENUM: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (0 == java_data.l) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] null-ref given!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + + *(jint *) uno_data = jni->GetIntField( + java_data.l, m_jni_info->m_field_Enum_m_value ); + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (0 == java_data.l) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] null-ref given!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + + if (0 == info) + info = m_jni_info->get_type_info( jni, type ); + JNI_compound_type_info const * comp_info = + static_cast< JNI_compound_type_info const * >( info ); + + typelib_CompoundTypeDescription * comp_td = + (typelib_CompoundTypeDescription *)comp_info->m_td.get(); + bool polymorphic + = comp_td->aBase.eTypeClass == typelib_TypeClass_STRUCT + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes != 0; + + sal_Int32 nPos = 0; + sal_Int32 nMembers = comp_td->nMembers; + try + { + if (0 != comp_td->pBaseTypeDescription) + { + map_to_uno( + jni, uno_data, java_data, + ((typelib_TypeDescription *) comp_td->pBaseTypeDescription) + ->pWeakRef, + comp_info->m_base, + assign, false /* no out param */ ); + } + + for ( ; nPos < nMembers; ++nPos ) + { + void * p = (char *)uno_data + comp_td->pMemberOffsets[ nPos ]; + typelib_TypeDescriptionReference * member_type = + comp_td->ppTypeRefs[ nPos ]; + jfieldID field_id = comp_info->m_fields[ nPos ]; + bool parameterizedType = polymorphic + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes[nPos]; + switch (member_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jchar *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jchar *) p = jni->GetCharField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jboolean *) p = false; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jboolean *) p = jni->GetBooleanField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_BYTE: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jbyte *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jbyte *) p = jni->GetByteField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jshort *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jshort *) p = jni->GetShortField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jint *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jint *) p = jni->GetIntField( java_data.l, field_id ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jlong *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jlong *) p = jni->GetLongField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_FLOAT: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jfloat *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jfloat *) p = jni->GetFloatField( + java_data.l, field_id ); + } + break; + case typelib_TypeClass_DOUBLE: + if (parameterizedType) { + JLocalAutoRef jo( + jni, jni->GetObjectField( java_data.l, field_id ) ); + if ( jo.get() == 0 ) { + *(jdouble *) p = 0; + } else { + jvalue val; + val.l = jo.get(); + map_to_uno( + jni, p, val, member_type, 0, assign, false, + true ); + } + } else { + *(jdouble *) p = jni->GetDoubleField( + java_data.l, field_id ); + } + break; + default: + { + JLocalAutoRef jo_field( jni ); + bool checkNull; + if (0 == field_id) + { + // special for Message: call Throwable.getMessage() + OSL_ASSERT( + type_equals( + type, + m_jni_info->m_Exception_type.getTypeLibType() ) + || type_equals( + type, + m_jni_info->m_RuntimeException_type. + getTypeLibType() ) ); + OSL_ASSERT( 0 == nPos ); // first member + // call getMessage() + jo_field.reset( + jni->CallObjectMethodA( + java_data.l, + m_jni_info->m_method_Throwable_getMessage, 0 ) + ); + jni.ensure_no_exception(); + checkNull = true; + } + else + { + jo_field.reset( + jni->GetObjectField( java_data.l, field_id ) ); + checkNull = parameterizedType; + } + if (checkNull && !jo_field.is()) { + createDefaultUnoValue(jni, p, member_type, 0, assign); + } else { + jvalue val; + val.l = jo_field.get(); + map_to_uno( + jni, p, val, member_type, 0, + assign, false /* no out param */ ); + } + break; + } + } + } + } + catch (...) + { + if (! assign) + { + // cleanup + for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup ) + { + void * p = + (char *)uno_data + comp_td->pMemberOffsets[ nCleanup ]; + uno_type_destructData( + p, comp_td->ppTypeRefs[ nCleanup ], 0 ); + } + if (0 != comp_td->pBaseTypeDescription) + { + uno_destructData( + uno_data, + (typelib_TypeDescription *) comp_td + ->pBaseTypeDescription, 0 ); + } + } + throw; + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + if (0 == java_data.l) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] null-ref given!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + + TypeDescr td( type ); + typelib_TypeDescriptionReference * element_type = + ((typelib_IndirectTypeDescription *)td.get())->pType; + + auto_ptr< rtl_mem > seq; + sal_Int32 nElements = jni->GetArrayLength( (jarray) java_data.l ); + + switch (element_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + seq.reset( seq_allocate( nElements, sizeof (sal_Unicode) ) ); + jni->GetCharArrayRegion( + (jcharArray) java_data.l, 0, nElements, + (jchar *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BOOLEAN: + seq.reset( seq_allocate( nElements, sizeof (sal_Bool) ) ); + jni->GetBooleanArrayRegion( + (jbooleanArray) java_data.l, 0, nElements, + (jboolean *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_BYTE: + seq.reset( seq_allocate( nElements, sizeof (sal_Int8) ) ); + jni->GetByteArrayRegion( + (jbyteArray) java_data.l, 0, nElements, + (jbyte *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + seq.reset( seq_allocate( nElements, sizeof (sal_Int16) ) ); + jni->GetShortArrayRegion( + (jshortArray) java_data.l, 0, nElements, + (jshort *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + seq.reset( seq_allocate( nElements, sizeof (sal_Int32) ) ); + jni->GetIntArrayRegion( + (jintArray) java_data.l, 0, nElements, + (jint *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + seq.reset( seq_allocate( nElements, sizeof (sal_Int64) ) ); + jni->GetLongArrayRegion( + (jlongArray) java_data.l, 0, nElements, + (jlong *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_FLOAT: + seq.reset( seq_allocate( nElements, sizeof (float) ) ); + jni->GetFloatArrayRegion( + (jfloatArray) java_data.l, 0, nElements, + (jfloat *)((uno_Sequence *)seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_DOUBLE: + seq.reset( seq_allocate( nElements, sizeof (double) ) ); + jni->GetDoubleArrayRegion( + (jdoubleArray) java_data.l, 0, nElements, + (jdouble *) ((uno_Sequence *) seq.get())->elements ); + jni.ensure_no_exception(); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + { + TypeDescr element_td( element_type ); + seq.reset( seq_allocate( nElements, element_td.get()->nSize ) ); + + JNI_type_info const * element_info; + if (typelib_TypeClass_STRUCT == element_type->eTypeClass || + typelib_TypeClass_EXCEPTION == element_type->eTypeClass || + typelib_TypeClass_INTERFACE == element_type->eTypeClass) + { + element_info = + m_jni_info->get_type_info( jni, element_td.get() ); + } + else + { + element_info = 0; + } + + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + try + { + JLocalAutoRef jo( + jni, jni->GetObjectArrayElement( + (jobjectArray) java_data.l, nPos ) ); + jni.ensure_no_exception(); + jvalue val; + val.l = jo.get(); + void * p = + ((uno_Sequence *)seq.get())->elements + + (nPos * element_td.get()->nSize); + map_to_uno( + jni, p, val, element_td.get()->pWeakRef, element_info, + false /* no assign */, false /* no out param */ ); + } + catch (...) + { + // cleanup + for ( sal_Int32 nCleanPos = 0; + nCleanPos < nPos; ++nCleanPos ) + { + void * p = + ((uno_Sequence *)seq.get())->elements + + (nCleanPos * element_td.get()->nSize); + uno_destructData( p, element_td.get(), 0 ); + } + throw; + } + } + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] unsupported sequence element" + " type: ") ); + buf.append( OUString::unacquired( &element_type->pTypeName ) ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } + + if (assign) + uno_destructData( uno_data, td.get(), 0 ); + *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release(); + break; + } + case typelib_TypeClass_INTERFACE: + { + JLocalAutoRef jo_out_holder( jni ); + if (out_param) + { + jo_out_holder.reset( + jni->GetObjectArrayElement( (jobjectArray) java_data.l, 0 ) ); + jni.ensure_no_exception(); + java_data.l = jo_out_holder.get(); + } + + if (0 == java_data.l) // null-ref + { + if (assign) + { + uno_Interface * p = *(uno_Interface **)uno_data; + if (0 != p) + (*p->release)( p ); + } + *(uno_Interface **)uno_data = 0; + } + else + { + if (0 == info) + info = m_jni_info->get_type_info( jni, type ); + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( info ); + uno_Interface * pUnoI = map_to_uno( jni, java_data.l, iface_info ); + if (assign) + { + uno_Interface * p = *(uno_Interface **)uno_data; + if (0 != p) + (*p->release)( p ); + } + *(uno_Interface **)uno_data = pUnoI; + } + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } +} + +//############################################################################## + +//______________________________________________________________________________ +void Bridge::map_to_java( + JNI_context const & jni, + jvalue * java_data, void const * uno_data, + typelib_TypeDescriptionReference * type, + JNI_type_info const * info /* maybe 0 */, + bool in_param, bool out_param, + bool special_wrapped_integral_types ) const +{ + switch (type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewCharArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetCharArrayRegion( + (jcharArray) jo_ar.get(), 0, 1, (jchar *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetCharArrayRegion( + (jcharArray) java_data->l, 0, 1, (jchar *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.c = *(jchar const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Character, + m_jni_info->m_ctor_Character_with_char, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->c = *(jchar const *) uno_data; + } + break; + case typelib_TypeClass_BOOLEAN: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewBooleanArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetBooleanArrayRegion( + (jbooleanArray) jo_ar.get(), + 0, 1, (jboolean *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetBooleanArrayRegion( + (jbooleanArray) java_data->l, + 0, 1, (jboolean *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.z = *(jboolean const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Boolean, + m_jni_info->m_ctor_Boolean_with_boolean, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->z = *(jboolean const *) uno_data; + } + break; + case typelib_TypeClass_BYTE: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewByteArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetByteArrayRegion( + (jbyteArray) jo_ar.get(), 0, 1, (jbyte *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetByteArrayRegion( + (jbyteArray) java_data->l, 0, 1, (jbyte *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.b = *(jbyte const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Byte, + m_jni_info->m_ctor_Byte_with_byte, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->b = *(jbyte const *) uno_data; + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewShortArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetShortArrayRegion( + (jshortArray) jo_ar.get(), 0, 1, (jshort *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetShortArrayRegion( + (jshortArray) java_data->l, 0, 1, (jshort *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.s = *(jshort const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Short, + m_jni_info->m_ctor_Short_with_short, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->s = *(jshort const *) uno_data; + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewIntArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetIntArrayRegion( + (jintArray) jo_ar.get(), 0, 1, (jint *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetIntArrayRegion( + (jintArray) java_data->l, 0, 1, (jint *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.i = *(jint const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Integer, + m_jni_info->m_ctor_Integer_with_int, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->i = *(jint const *) uno_data; + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewLongArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetLongArrayRegion( + (jlongArray)jo_ar.get(), 0, 1, (jlong *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetLongArrayRegion( + (jlongArray)java_data->l, 0, 1, (jlong *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.j = *(jlong const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Long, + m_jni_info->m_ctor_Long_with_long, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->j = *(jlong const *) uno_data; + } + break; + case typelib_TypeClass_FLOAT: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewFloatArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetFloatArrayRegion( + (jfloatArray) jo_ar.get(), 0, 1, (jfloat *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetFloatArrayRegion( + (jfloatArray) java_data->l, 0, 1, (jfloat *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.f = *(jfloat const *) uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Float, + m_jni_info->m_ctor_Float_with_float, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->f = *(jfloat const *) uno_data; + } + break; + case typelib_TypeClass_DOUBLE: + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_ar( jni, jni->NewDoubleArray( 1 ) ); + jni.ensure_no_exception(); + if (in_param) + { + jni->SetDoubleArrayRegion( + (jdoubleArray) jo_ar.get(), + 0, 1, (jdouble *) uno_data ); + jni.ensure_no_exception(); + } + java_data->l = jo_ar.release(); + } + else + { + if (in_param) + { + jni->SetDoubleArrayRegion( + (jdoubleArray) java_data->l, + 0, 1, (jdouble *) uno_data ); + jni.ensure_no_exception(); + } + } + } + else if (special_wrapped_integral_types) + { + jvalue arg; + arg.d = *(double const *)uno_data; + java_data->l = jni->NewObjectA( + m_jni_info->m_class_Double, + m_jni_info->m_ctor_Double_with_double, &arg ); + jni.ensure_no_exception(); + } + else + { + java_data->d = *(jdouble const *) uno_data; + } + break; + case typelib_TypeClass_STRING: + { + if (out_param) + { + JLocalAutoRef jo_in( jni ); + if (in_param) + { + jo_in.reset( + ustring_to_jstring( + jni, *(rtl_uString * const *) uno_data ) ); + } + if (0 == java_data->l) + { + java_data->l = jni->NewObjectArray( + 1, m_jni_info->m_class_String, jo_in.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_in.get() ); + jni.ensure_no_exception(); + } + } + else + { + OSL_ASSERT( in_param ); + java_data->l = + ustring_to_jstring( jni, *(rtl_uString * const *) uno_data ); + } + break; + } + case typelib_TypeClass_TYPE: + { + if (out_param) + { + JLocalAutoRef jo_in( jni ); + if (in_param) + { + jo_in.reset( + create_type( + jni, + *(typelib_TypeDescriptionReference * const *) uno_data ) + ); + } + if (0 == java_data->l) + { + java_data->l = jni->NewObjectArray( + 1, m_jni_info->m_class_Type, jo_in.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_in.get() ); + jni.ensure_no_exception(); + } + } + else + { + OSL_ASSERT( in_param ); + java_data->l = + create_type( + jni, + *(typelib_TypeDescriptionReference * const *) uno_data ); + } + break; + } + case typelib_TypeClass_ANY: + { + JLocalAutoRef jo_any( jni ); + if (in_param) + { + uno_Any const * pAny = (uno_Any const *)uno_data; + +#if defined BRIDGES_JNI_UNO_FORCE_BOXED_ANY + if (typelib_TypeClass_VOID == pAny->pType->eTypeClass) + { + jo_any.reset( + jni->NewLocalRef( m_jni_info->m_object_Any_VOID ) ); + } + else + { + jvalue args[ 2 ]; + map_to_java( + jni, &args[ 1 ], pAny->pData, pAny->pType, 0, + true /* in */, false /* no out */, + true /* create integral wrappers */ ); + jo_any.reset( args[ 1 ].l ); + // build up com.sun.star.uno.Any + JLocalAutoRef jo_type( jni, create_type( jni, pAny->pType ) ); + args[ 0 ].l = jo_type.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + } +#else + switch (pAny->pType->eTypeClass) + { + case typelib_TypeClass_VOID: + jo_any.reset( + jni->NewLocalRef( m_jni_info->m_object_Any_VOID ) ); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + { + jvalue args[ 2 ]; + args[ 0 ].s = *(jshort const *) pAny->pData; + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + m_jni_info->m_class_Short, + m_jni_info->m_ctor_Short_with_short, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = m_jni_info->m_object_Type_UNSIGNED_SHORT; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_UNSIGNED_LONG: + { + jvalue args[ 2 ]; + args[ 0 ].i = *(jint const *) pAny->pData; + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + m_jni_info->m_class_Integer, + m_jni_info->m_ctor_Integer_with_int, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = m_jni_info->m_object_Type_UNSIGNED_LONG; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_UNSIGNED_HYPER: + { + jvalue args[ 2 ]; + args[ 0 ].j = *(jlong const *) pAny->pData; + JLocalAutoRef jo_val( + jni, jni->NewObjectA( + m_jni_info->m_class_Long, + m_jni_info->m_ctor_Long_with_long, args ) ); + jni.ensure_no_exception(); + // box up in com.sun.star.uno.Any + args[ 0 ].l = m_jni_info->m_object_Type_UNSIGNED_HYPER; + args[ 1 ].l = jo_val.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + case typelib_TypeClass_STRING: // opt strings + jo_any.reset( ustring_to_jstring( + jni, (rtl_uString *) pAny->pReserved ) ); + break; + case typelib_TypeClass_SEQUENCE: + { + jvalue java_data2; + // prefetch sequence td + TypeDescr seq_td( pAny->pType ); + map_to_java( + jni, &java_data2, pAny->pData, seq_td.get()->pWeakRef, 0, + true /* in */, false /* no out */, + true /* create integral wrappers */ ); + jo_any.reset( java_data2.l ); + + // determine inner element type + ::com::sun::star::uno::Type element_type( + ((typelib_IndirectTypeDescription *)seq_td.get())->pType ); + while (typelib_TypeClass_SEQUENCE == + element_type.getTypeLibType()->eTypeClass) + { + TypeDescr element_td( element_type.getTypeLibType() ); + typelib_typedescriptionreference_assign( + reinterpret_cast< typelib_TypeDescriptionReference ** >( + &element_type ), + ((typelib_IndirectTypeDescription *)element_td.get()) + ->pType ); + } + // box up only if unsigned element type + switch (element_type.getTypeLibType()->eTypeClass) + { + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_UNSIGNED_HYPER: + { + jvalue args[ 2 ]; + JLocalAutoRef jo_type( + jni, create_type( jni, seq_td.get()->pWeakRef ) ); + args[ 0 ].l = jo_type.get(); + args[ 1 ].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + break; + } + default: + break; + } + break; + } + case typelib_TypeClass_INTERFACE: + { + uno_Interface * pUnoI = (uno_Interface *)pAny->pReserved; + if (is_XInterface( pAny->pType )) + { + if (0 != pUnoI) + { + jo_any.reset( + map_to_java( + jni, pUnoI, + m_jni_info->m_XInterface_type_info ) ); + } + // else: empty XInterface ref maps to null-ref + } + else + { + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( + m_jni_info->get_type_info( jni, pAny->pType ) ); + if (0 != pUnoI) + { + jo_any.reset( map_to_java( jni, pUnoI, iface_info ) ); + } + // box up in com.sun.star.uno.Any + jvalue args[ 2 ]; + args[ 0 ].l = iface_info->m_type; + args[ 1 ].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args ) ); + jni.ensure_no_exception(); + } + break; + } + case typelib_TypeClass_STRUCT: + { + // Do not lose information about type arguments of instantiated + // polymorphic struct types: + rtl::OUString const & name = rtl::OUString::unacquired( + &pAny->pType->pTypeName); + OSL_ASSERT(name.getLength() > 0); + if (name[name.getLength() - 1] == '>') + { + // Box up in com.sun.star.uno.Any: + JLocalAutoRef jo_type(jni, create_type(jni, pAny->pType)); + jvalue java_data2; + map_to_java( + jni, &java_data2, pAny->pData, pAny->pType, 0, true, + false); + jo_any.reset(java_data2.l); + jvalue args[2]; + args[0].l = jo_type.get(); + args[1].l = jo_any.get(); + jo_any.reset( + jni->NewObjectA( + m_jni_info->m_class_Any, + m_jni_info->m_ctor_Any_with_Type_Object, args)); + jni.ensure_no_exception(); + break; + } + // fall through + } + default: + { + jvalue java_data2; + map_to_java( + jni, &java_data2, pAny->pData, pAny->pType, 0, + true /* in */, false /* no out */, + true /* create integral wrappers */ ); + jo_any.reset( java_data2.l ); + break; + } + } +#endif + } + + if (out_param) + { + if (0 == java_data->l) + { + java_data->l = jni->NewObjectArray( + 1, m_jni_info->m_class_Object, jo_any.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_any.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_any.release(); + } + break; + } + case typelib_TypeClass_ENUM: + { + OUString const & type_name = OUString::unacquired( &type->pTypeName ); + OString class_name( + OUStringToOString( type_name, RTL_TEXTENCODING_JAVA_UTF8 ) ); + JLocalAutoRef jo_enum_class( + jni, find_class( jni, class_name.getStr() ) ); + + JLocalAutoRef jo_enum( jni ); + if (in_param) + { + // call static <enum_class>.fromInt( int ) + OStringBuffer sig_buf( 5 + class_name.getLength() ); + sig_buf.append( RTL_CONSTASCII_STRINGPARAM("(I)L") ); + sig_buf.append( class_name.replace( '.', '/' ) ); + sig_buf.append( ';' ); + OString sig( sig_buf.makeStringAndClear() ); + jmethodID method_id = jni->GetStaticMethodID( + (jclass) jo_enum_class.get(), "fromInt", sig.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != method_id ); + + jvalue arg; + arg.i = *(jint const *) uno_data; + jo_enum.reset( + jni->CallStaticObjectMethodA( + (jclass) jo_enum_class.get(), method_id, &arg ) ); + jni.ensure_no_exception(); + } + if (out_param) + { + if (0 == java_data->l) + { + java_data->l = jni->NewObjectArray( + 1, (jclass) jo_enum_class.get(), jo_enum.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_enum.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_enum.release(); + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + if (0 == info) + info = m_jni_info->get_type_info( jni, type ); + JNI_compound_type_info const * comp_info = + static_cast< JNI_compound_type_info const * >( info ); + + JLocalAutoRef jo_comp( jni ); + if (in_param) + { + if (typelib_TypeClass_EXCEPTION == type->eTypeClass) + { + JLocalAutoRef jo_message( + jni, ustring_to_jstring( jni, *(rtl_uString **)uno_data ) ); + jvalue arg; + arg.l = jo_message.get(); + jo_comp.reset( + jni->NewObjectA( + comp_info->m_class, comp_info->m_exc_ctor, &arg ) ); + jni.ensure_no_exception(); + } + else + { + jo_comp.reset( jni->AllocObject( comp_info->m_class ) ); + jni.ensure_no_exception(); + } + + for ( JNI_compound_type_info const * linfo = comp_info; + 0 != linfo; + linfo = static_cast< JNI_compound_type_info const * >( + linfo->m_base ) ) + { + typelib_CompoundTypeDescription * comp_td = + (typelib_CompoundTypeDescription *)linfo->m_td.get(); + typelib_TypeDescriptionReference ** ppMemberTypeRefs = + comp_td->ppTypeRefs; + sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets; + bool polymorphic + = comp_td->aBase.eTypeClass == typelib_TypeClass_STRUCT + && reinterpret_cast< typelib_StructTypeDescription * >( + comp_td)->pParameterizedTypes != 0; + for ( sal_Int32 nPos = comp_td->nMembers; nPos--; ) + { + jfieldID field_id = linfo->m_fields[ nPos ]; + if (0 != field_id) + { + void const * p = + (char const *)uno_data + pMemberOffsets[ nPos ]; + typelib_TypeDescriptionReference * member_type = + ppMemberTypeRefs[ nPos ]; + bool parameterizedType = polymorphic + && (reinterpret_cast< + typelib_StructTypeDescription * >(comp_td)-> + pParameterizedTypes[nPos]); + switch (member_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (parameterizedType) { + jvalue arg; + arg.c = *(jchar const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Character, + m_jni_info->m_ctor_Character_with_char, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetCharField( + jo_comp.get(), + field_id, *(jchar const *) p ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (parameterizedType) { + jvalue arg; + arg.z = *(jboolean const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Boolean, + m_jni_info->m_ctor_Boolean_with_boolean, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetBooleanField( + jo_comp.get(), + field_id, *(jboolean const *) p ); + } + break; + case typelib_TypeClass_BYTE: + if (parameterizedType) { + jvalue arg; + arg.b = *(jbyte const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Byte, + m_jni_info->m_ctor_Byte_with_byte, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetByteField( + jo_comp.get(), + field_id, *(jbyte const *) p ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (parameterizedType) { + jvalue arg; + arg.s = *(jshort const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Short, + m_jni_info->m_ctor_Short_with_short, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetShortField( + jo_comp.get(), + field_id, *(jshort const *) p ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (parameterizedType) { + jvalue arg; + arg.i = *(jint const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Integer, + m_jni_info->m_ctor_Integer_with_int, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetIntField( + jo_comp.get(), + field_id, *(jint const *) p ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (parameterizedType) { + jvalue arg; + arg.j = *(jlong const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Long, + m_jni_info->m_ctor_Long_with_long, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetLongField( + jo_comp.get(), + field_id, *(jlong const *) p ); + } + break; + case typelib_TypeClass_FLOAT: + if (parameterizedType) { + jvalue arg; + arg.f = *(jfloat const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Float, + m_jni_info->m_ctor_Float_with_float, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetFloatField( + jo_comp.get(), + field_id, *(jfloat const *) p ); + } + break; + case typelib_TypeClass_DOUBLE: + if (parameterizedType) { + jvalue arg; + arg.d = *(jdouble const *) p; + JLocalAutoRef jo( + jni, + jni->NewObjectA( + m_jni_info->m_class_Double, + m_jni_info->m_ctor_Double_with_double, + &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectField( + jo_comp.get(), field_id, jo.get() ); + } else { + jni->SetDoubleField( + jo_comp.get(), + field_id, *(jdouble const *) p ); + } + break; + case typelib_TypeClass_STRING: // string opt here + { + JLocalAutoRef jo_string( + jni, ustring_to_jstring( + jni, *(rtl_uString * const *) p ) ); + jni->SetObjectField( + jo_comp.get(), field_id, jo_string.get() ); + break; + } + default: + { + jvalue java_data2; + map_to_java( + jni, &java_data2, p, member_type, 0, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_obj( jni, java_data2.l ); + jni->SetObjectField( + jo_comp.get(), field_id, jo_obj.get() ); + break; + } + } + } + } + } + } + if (out_param) + { + if (0 == java_data->l) + { + java_data->l = + jni->NewObjectArray( 1, comp_info->m_class, jo_comp.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_comp.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_comp.release(); + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + // xxx todo: possible opt for pure out sequences + JLocalAutoRef jo_ar( jni ); + + sal_Int32 nElements; + uno_Sequence const * seq = 0; + if (in_param) + { + seq = *(uno_Sequence * const *)uno_data; + nElements = seq->nElements; + } + else + { + nElements = 0; + } + + TypeDescr td( type ); + typelib_TypeDescriptionReference * element_type = + ((typelib_IndirectTypeDescription *)td.get())->pType; + + switch (element_type->eTypeClass) + { + case typelib_TypeClass_CHAR: + jo_ar.reset( jni->NewCharArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetCharArrayRegion( + (jcharArray) jo_ar.get(), + 0, nElements, (jchar *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_BOOLEAN: + jo_ar.reset( jni->NewBooleanArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetBooleanArrayRegion( + (jbooleanArray) jo_ar.get(), + 0, nElements, (jboolean *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_BYTE: + jo_ar.reset( jni->NewByteArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetByteArrayRegion( + (jbyteArray) jo_ar.get(), + 0, nElements, (jbyte *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + jo_ar.reset( jni->NewShortArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetShortArrayRegion( + (jshortArray) jo_ar.get(), + 0, nElements, (jshort *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + jo_ar.reset( jni->NewIntArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetIntArrayRegion( + (jintArray) jo_ar.get(), + 0, nElements, (jint *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + jo_ar.reset( jni->NewLongArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetLongArrayRegion( + (jlongArray) jo_ar.get(), + 0, nElements, (jlong *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_FLOAT: + jo_ar.reset( jni->NewFloatArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetFloatArrayRegion( + (jfloatArray) jo_ar.get(), + 0, nElements, (jfloat *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_DOUBLE: + jo_ar.reset( jni->NewDoubleArray( nElements ) ); + jni.ensure_no_exception(); + if (0 < nElements) + { + jni->SetDoubleArrayRegion( + (jdoubleArray) jo_ar.get(), + 0, nElements, (jdouble *) seq->elements ); + jni.ensure_no_exception(); + } + break; + case typelib_TypeClass_STRING: + jo_ar.reset( + jni->NewObjectArray( + nElements, m_jni_info->m_class_String, 0 ) ); + jni.ensure_no_exception(); + if (in_param) + { + rtl_uString * const * pp = + (rtl_uString * const *) seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + JLocalAutoRef jo_string( + jni, ustring_to_jstring( jni, pp[ nPos ] ) ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_string.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_TYPE: + jo_ar.reset( + jni->NewObjectArray( nElements, m_jni_info->m_class_Type, 0 ) ); + jni.ensure_no_exception(); + if (in_param) + { + typelib_TypeDescriptionReference * const * pp = + (typelib_TypeDescriptionReference * const *)seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, &pp[ nPos ], element_type, 0, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_ANY: + jo_ar.reset( + jni->NewObjectArray( + nElements, m_jni_info->m_class_Object, 0 ) ); + jni.ensure_no_exception(); + if (in_param) + { + uno_Any const * p = (uno_Any const *)seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, &p[ nPos ], element_type, 0, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + case typelib_TypeClass_ENUM: + { + OUString const & element_type_name = + OUString::unacquired( &element_type->pTypeName ); + OString class_name( + OUStringToOString( + element_type_name, RTL_TEXTENCODING_JAVA_UTF8 ) ); + JLocalAutoRef jo_enum_class( + jni, find_class( jni, class_name.getStr() ) ); + + jo_ar.reset( + jni->NewObjectArray( + nElements, (jclass) jo_enum_class.get(), 0 ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + // call static <enum_class>.fromInt( int ) + OStringBuffer sig_buf( 5 + class_name.getLength() ); + sig_buf.append( RTL_CONSTASCII_STRINGPARAM("(I)L") ); + sig_buf.append( class_name.replace( '.', '/' ) ); + sig_buf.append( ';' ); + OString sig( sig_buf.makeStringAndClear() ); + jmethodID method_id = jni->GetStaticMethodID( + (jclass) jo_enum_class.get(), "fromInt", sig.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != method_id ); + + sal_Int32 const * p = (sal_Int32 const *)seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue arg; + arg.i = p[ nPos ]; + JLocalAutoRef jo_enum( + jni, jni->CallStaticObjectMethodA( + (jclass) jo_enum_class.get(), method_id, &arg ) ); + jni.ensure_no_exception(); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_enum.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + JNI_type_info const * element_info = + m_jni_info->get_type_info( jni, element_type ); + + jo_ar.reset( + jni->NewObjectArray( nElements, element_info->m_class, 0 ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + char * p = (char *)seq->elements; + sal_Int32 nSize = element_info->m_td.get()->nSize; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue val; + map_to_java( + jni, &val, p + (nSize * nPos), + element_type, element_info, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_element( jni, val.l ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + OStringBuffer buf( 64 ); + JNI_info::append_sig( + &buf, element_type, false /* use class XInterface */, + false /* '.' instead of '/' */ ); + OString class_name( buf.makeStringAndClear() ); + JLocalAutoRef jo_seq_class( + jni, find_class( jni, class_name.getStr() ) ); + + jo_ar.reset( + jni->NewObjectArray( + nElements, (jclass) jo_seq_class.get(), 0 ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + TypeDescr element_td( element_type ); + uno_Sequence ** elements = (uno_Sequence **) seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + jvalue java_data2; + map_to_java( + jni, &java_data2, elements + nPos, element_type, 0, + true /* in */, false /* no out */ ); + JLocalAutoRef jo_seq( jni, java_data2.l ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), nPos, jo_seq.get() ); + jni.ensure_no_exception(); + } + } + break; + } + case typelib_TypeClass_INTERFACE: + { + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( + m_jni_info->get_type_info( jni, element_type ) ); + + jo_ar.reset( + jni->NewObjectArray( nElements, iface_info->m_class, 0 ) ); + jni.ensure_no_exception(); + + if (0 < nElements) + { + uno_Interface ** pp = (uno_Interface **)seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + uno_Interface * pUnoI = pp[ nPos ]; + if (0 != pUnoI) + { + JLocalAutoRef jo_element( + jni, map_to_java( jni, pUnoI, iface_info ) ); + jni->SetObjectArrayElement( + (jobjectArray) jo_ar.get(), + nPos, jo_element.get() ); + jni.ensure_no_exception(); + } + } + } + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_java():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("] unsupported element type: ") ); + buf.append( OUString::unacquired( &element_type->pTypeName ) ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } + + if (out_param) + { + if (0 == java_data->l) + { + JLocalAutoRef jo_element_class( + jni, jni->GetObjectClass( jo_ar.get() ) ); + if (in_param) + { + java_data->l = jni->NewObjectArray( + 1, (jclass) jo_element_class.get(), jo_ar.get() ); + } + else + { + java_data->l = jni->NewObjectArray( + 1, (jclass) jo_element_class.get(), 0 ); + } + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_ar.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_ar.release(); + } + break; + } + case typelib_TypeClass_INTERFACE: + { + JLocalAutoRef jo_iface( jni ); + if (in_param) + { + uno_Interface * pUnoI = *(uno_Interface * const *)uno_data; + if (0 != pUnoI) + { + if (0 == info) + info = m_jni_info->get_type_info( jni, type ); + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( info ); + jo_iface.reset( map_to_java( jni, pUnoI, iface_info ) ); + } + } + if (out_param) + { + if (0 == java_data->l) + { + if (0 == info) + info = m_jni_info->get_type_info( jni, type ); + java_data->l = + jni->NewObjectArray( 1, info->m_class, jo_iface.get() ); + jni.ensure_no_exception(); + } + else + { + jni->SetObjectArrayElement( + (jobjectArray) java_data->l, 0, jo_iface.get() ); + jni.ensure_no_exception(); + } + } + else + { + java_data->l = jo_iface.release(); + } + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_java():") ); + buf.append( OUString::unacquired( &type->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_helper.h b/bridges/source/jni_uno/jni_helper.h new file mode 100644 index 000000000000..293bf82d868e --- /dev/null +++ b/bridges/source/jni_uno/jni_helper.h @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_JNI_HELPER_H +#define INCLUDED_JNI_HELPER_H + +#include "jni_base.h" +#include "jni_info.h" + + +namespace jni_uno +{ + +//------------------------------------------------------------------------------ +inline void jstring_to_ustring( + JNI_context const & jni, rtl_uString ** out_ustr, jstring jstr ) +{ + if (0 == jstr) + { + rtl_uString_new( out_ustr ); + } + else + { + jsize len = jni->GetStringLength( jstr ); + ::std::auto_ptr< rtl_mem > mem( + rtl_mem::allocate( + sizeof (rtl_uString) + (len * sizeof (sal_Unicode)) ) ); + rtl_uString * ustr = (rtl_uString *)mem.get(); + jni->GetStringRegion( jstr, 0, len, (jchar *) ustr->buffer ); + jni.ensure_no_exception(); + ustr->refCount = 1; + ustr->length = len; + ustr->buffer[ len ] = '\0'; + mem.release(); + if (0 != *out_ustr) + rtl_uString_release( *out_ustr ); + *out_ustr = ustr; + } +} + +//------------------------------------------------------------------------------ +inline ::rtl::OUString jstring_to_oustring( + JNI_context const & jni, jstring jstr ) +{ + rtl_uString * ustr = 0; + jstring_to_ustring( jni, &ustr, jstr ); + return ::rtl::OUString( ustr, SAL_NO_ACQUIRE ); +} + +//------------------------------------------------------------------------------ +inline jstring ustring_to_jstring( + JNI_context const & jni, rtl_uString const * ustr ) +{ + jstring jstr = jni->NewString( (jchar const *) ustr->buffer, ustr->length ); + jni.ensure_no_exception(); + return jstr; +} + + +//------------------------------------------------------------------------------ +// if inException, does not handle exceptions, in which case returned value will +// be null if exception occurred: +inline jclass find_class( + JNI_context const & jni, char const * class_name, bool inException = false ) +{ + // find_class may be called before the JNI_info is set: + jclass c=0; + jmethodID m; + JNI_info const * info = jni.get_info(); + if (info == 0) { + jni.getClassForName(&c, &m); + if (c == 0) { + if (inException) { + return 0; + } + jni.ensure_no_exception(); + } + } else { + c = info->m_class_Class; + m = info->m_method_Class_forName; + } + return jni.findClass(class_name, c, m, inException); +} + + +//------------------------------------------------------------------------------ +inline jobject create_type( JNI_context const & jni, jclass clazz ) +{ + JNI_info const * jni_info = jni.get_info(); + jvalue arg; + arg.l = clazz; + jobject jo_type = jni->NewObjectA( + jni_info->m_class_Type, jni_info->m_ctor_Type_with_Class, &arg ); + jni.ensure_no_exception(); + return jo_type; +} + +//------------------------------------------------------------------------------ +inline jobject create_type( + JNI_context const & jni, typelib_TypeDescriptionReference * type ) +{ + JNI_info const * jni_info = jni.get_info(); + jvalue args[ 2 ]; + // get type class + args[ 0 ].i = type->eTypeClass; + JLocalAutoRef jo_type_class( + jni, jni->CallStaticObjectMethodA( + jni_info->m_class_TypeClass, + jni_info->m_method_TypeClass_fromInt, args ) ); + jni.ensure_no_exception(); + // construct type + JLocalAutoRef jo_type_name( + jni, ustring_to_jstring( jni, type->pTypeName ) ); + args[ 0 ].l = jo_type_name.get(); + args[ 1 ].l = jo_type_class.get(); + jobject jo_type = jni->NewObjectA( + jni_info->m_class_Type, + jni_info->m_ctor_Type_with_Name_TypeClass, args ); + jni.ensure_no_exception(); + return jo_type; +} + +//------------------------------------------------------------------------------ +inline jobject compute_oid( JNI_context const & jni, jobject jo ) +{ + JNI_info const * jni_info = jni.get_info(); + jvalue arg; + arg.l= jo; + jobject jo_oid = jni->CallStaticObjectMethodA( + jni_info->m_class_UnoRuntime, + jni_info->m_method_UnoRuntime_generateOid, &arg ); + jni.ensure_no_exception(); + return jo_oid; +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_info.cxx b/bridges/source/jni_uno/jni_info.cxx new file mode 100644 index 000000000000..6df598859d0a --- /dev/null +++ b/bridges/source/jni_uno/jni_info.cxx @@ -0,0 +1,999 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include "jni_bridge.h" + +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "jvmaccess/unovirtualmachine.hxx" +#include "rtl/string.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" + +#include "uno/lbnames.h" + + +namespace css = ::com::sun::star; +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + +namespace jni_uno +{ + +//______________________________________________________________________________ +JNI_type_info::JNI_type_info( + JNI_context const & jni, typelib_TypeDescription * td ) + : m_td( td ), + m_class( 0 ) +{ + m_td.makeComplete(); + if (! m_td.get()->bComplete) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") ); + buf.append( OUString::unacquired( &m_td.get()->pTypeName ) ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } +} + + +//______________________________________________________________________________ +void JNI_interface_type_info::destroy( JNIEnv * jni_env ) +{ + JNI_type_info::destruct( jni_env ); + jni_env->DeleteGlobalRef( m_proxy_ctor ); + jni_env->DeleteGlobalRef( m_type ); + delete [] m_methods; + delete this; +} + +//______________________________________________________________________________ +JNI_interface_type_info::JNI_interface_type_info( + JNI_context const & jni, typelib_TypeDescription * td_ ) + : JNI_type_info( jni, td_ ) +{ + OSL_ASSERT( typelib_TypeClass_INTERFACE == m_td.get()->eTypeClass ); + + OUString const & uno_name = OUString::unacquired( &m_td.get()->pTypeName ); + JNI_info const * jni_info = jni.get_info(); + + JLocalAutoRef jo_class( + jni, + find_class( + jni, + ( OUStringToOString( uno_name, RTL_TEXTENCODING_JAVA_UTF8 ). + getStr() ) ) ); + JLocalAutoRef jo_type( jni, create_type( jni, (jclass) jo_class.get() ) ); + + // get proxy ctor + jvalue arg; + arg.l = jo_class.get(); + JLocalAutoRef jo_proxy_ctor( + jni, jni->CallStaticObjectMethodA( + jni_info->m_class_JNI_proxy, + jni_info->m_method_JNI_proxy_get_proxy_ctor, &arg ) ); + + if (is_XInterface( m_td.get()->pWeakRef )) + { + m_methods = 0; // no methods + } + else + { + // retrieve method ids for all direct members + try + { + typelib_InterfaceTypeDescription * td = + reinterpret_cast< typelib_InterfaceTypeDescription * >( + m_td.get() ); + m_methods = new jmethodID[ td->nMapFunctionIndexToMemberIndex ]; + sal_Int32 nMethodIndex = 0; + typelib_TypeDescriptionReference ** ppMembers = td->ppMembers; + sal_Int32 nMembers = td->nMembers; + + for ( sal_Int32 nPos = 0; nPos < nMembers; ++nPos ) + { + TypeDescr member_td( ppMembers[ nPos ] ); + + OStringBuffer sig_buf( 64 ); + + if (typelib_TypeClass_INTERFACE_METHOD == + member_td.get()->eTypeClass) // method + { + typelib_InterfaceMethodTypeDescription * method_td = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member_td.get() ); + + sig_buf.append( '(' ); + for ( sal_Int32 i = 0; i < method_td->nParams; ++i ) + { + typelib_MethodParameter const & param = + method_td->pParams[ i ]; + if (param.bOut) + sig_buf.append( '[' ); + JNI_info::append_sig( &sig_buf, param.pTypeRef ); + } + sig_buf.append( ')' ); + JNI_info::append_sig( &sig_buf, method_td->pReturnTypeRef ); + + OString method_signature( sig_buf.makeStringAndClear() ); + OString method_name( + OUStringToOString( OUString::unacquired( + &method_td->aBase.pMemberName ), + RTL_TEXTENCODING_JAVA_UTF8 ) ); + + m_methods[ nMethodIndex ] = jni->GetMethodID( + (jclass) jo_class.get(), method_name.getStr(), + method_signature.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_methods[ nMethodIndex ] ); + ++nMethodIndex; + } + else // attribute + { + OSL_ASSERT( + typelib_TypeClass_INTERFACE_ATTRIBUTE == + member_td.get()->eTypeClass ); + typelib_InterfaceAttributeTypeDescription * attribute_td = + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member_td.get() ); + + // type sig + JNI_info::append_sig( + &sig_buf, attribute_td->pAttributeTypeRef ); + OString type_sig( sig_buf.makeStringAndClear() ); + sig_buf.ensureCapacity( 64 ); + // member name + OUString const & member_name = + OUString::unacquired( + &attribute_td->aBase.pMemberName ); + + // getter + sig_buf.append( RTL_CONSTASCII_STRINGPARAM("()") ); + sig_buf.append( type_sig ); + OString method_signature( sig_buf.makeStringAndClear() ); + OUStringBuffer name_buf( 3 + member_name.getLength() ); + name_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("get") ); + name_buf.append( member_name ); + OString method_name( + OUStringToOString( + name_buf.makeStringAndClear(), + RTL_TEXTENCODING_JAVA_UTF8 ) ); + m_methods[ nMethodIndex ] = jni->GetMethodID( + (jclass) jo_class.get(), method_name.getStr(), + method_signature.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_methods[ nMethodIndex ] ); + ++nMethodIndex; + if (! attribute_td->bReadOnly) + { + // setter + sig_buf.ensureCapacity( 64 ); + sig_buf.append( '(' ); + sig_buf.append( type_sig ); + sig_buf.append( RTL_CONSTASCII_STRINGPARAM(")V") ); + method_signature = sig_buf.makeStringAndClear(); + name_buf.ensureCapacity( 3 + member_name.getLength() ); + name_buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("set") ); + name_buf.append( member_name ); + method_name = OUStringToOString( + name_buf.makeStringAndClear(), + RTL_TEXTENCODING_JAVA_UTF8 ); + m_methods[ nMethodIndex ] = jni->GetMethodID( + (jclass) jo_class.get(), method_name.getStr(), + method_signature.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_methods[ nMethodIndex ] ); + ++nMethodIndex; + } + } + } + } + catch (...) + { + delete [] m_methods; + throw; + } + } + m_class = (jclass) jni->NewGlobalRef( jo_class.get() ); + m_type = jni->NewGlobalRef( jo_type.get() ); + m_proxy_ctor = jni->NewGlobalRef( jo_proxy_ctor.get() ); +} + + +//______________________________________________________________________________ +void JNI_compound_type_info::destroy( JNIEnv * jni_env ) +{ + JNI_type_info::destruct( jni_env ); + delete [] m_fields; + delete this; +} + +//______________________________________________________________________________ +JNI_compound_type_info::JNI_compound_type_info( + JNI_context const & jni, typelib_TypeDescription * td_ ) + : JNI_type_info( jni, td_ ), + m_exc_ctor( 0 ), + m_fields( 0 ) +{ + OSL_ASSERT( typelib_TypeClass_STRUCT == m_td.get()->eTypeClass || + typelib_TypeClass_EXCEPTION == m_td.get()->eTypeClass ); + typelib_CompoundTypeDescription * td = + reinterpret_cast< typelib_CompoundTypeDescription * >( m_td.get() ); + + OUString const & uno_name = + OUString::unacquired( &((typelib_TypeDescription *)td)->pTypeName ); + + // Erase type arguments of instantiated polymorphic struct types: + OUString nucleus; + sal_Int32 i = uno_name.indexOf( '<' ); + if ( i < 0 ) { + nucleus = uno_name; + } else { + nucleus = uno_name.copy( 0, i ); + } + JLocalAutoRef jo_class( + jni, + find_class( + jni, + OUStringToOString( + nucleus, RTL_TEXTENCODING_JAVA_UTF8 ).getStr() ) ); + + JNI_info const * jni_info = jni.get_info(); + + if (typelib_TypeClass_EXCEPTION == m_td.get()->eTypeClass) + { + // retrieve exc ctor( msg ) + m_exc_ctor = jni->GetMethodID( + (jclass) jo_class.get(), "<init>", "(Ljava/lang/String;)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_exc_ctor ); + } + + // retrieve info for base type + typelib_TypeDescription * base_td = + reinterpret_cast< typelib_TypeDescription * >( + td->pBaseTypeDescription ); + m_base = (0 == base_td ? 0 : jni_info->get_type_info( jni, base_td )); + + try + { + if (type_equals( + ((typelib_TypeDescription *)td)->pWeakRef, + jni_info->m_Exception_type.getTypeLibType() ) || + type_equals( + ((typelib_TypeDescription *)td)->pWeakRef, + jni_info->m_RuntimeException_type.getTypeLibType() )) + { + m_fields = new jfieldID[ 2 ]; + m_fields[ 0 ] = 0; // special Throwable.getMessage() + // field Context + m_fields[ 1 ] = jni->GetFieldID( + (jclass) jo_class.get(), "Context", "Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_fields[ 1 ] ); + } + else + { + // retrieve field ids for all direct members + sal_Int32 nMembers = td->nMembers; + m_fields = new jfieldID[ nMembers ]; + + for ( sal_Int32 nPos = 0; nPos < nMembers; ++nPos ) + { + OString sig; + if (td->aBase.eTypeClass == typelib_TypeClass_STRUCT + && reinterpret_cast< typelib_StructTypeDescription * >( + td)->pParameterizedTypes != 0 + && reinterpret_cast< typelib_StructTypeDescription * >( + td)->pParameterizedTypes[nPos]) + { + sig = OString( + RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")); + } else { + OStringBuffer sig_buf( 32 ); + JNI_info::append_sig( &sig_buf, td->ppTypeRefs[ nPos ] ); + sig = sig_buf.makeStringAndClear(); + } + + OString member_name( + OUStringToOString( + OUString::unacquired( &td->ppMemberNames[ nPos ] ), + RTL_TEXTENCODING_JAVA_UTF8 ) ); + + m_fields[ nPos ] = jni->GetFieldID( + (jclass) jo_class.get(), member_name.getStr(), + sig.getStr() ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_fields[ nPos ] ); + } + } + } + catch (...) + { + delete [] m_fields; + throw; + } + + m_class = (jclass) jni->NewGlobalRef( jo_class.get() ); +} + + +//______________________________________________________________________________ +JNI_type_info const * JNI_info::create_type_info( + JNI_context const & jni, typelib_TypeDescription * td ) const +{ + OUString const & uno_name = OUString::unacquired( &td->pTypeName ); + + JNI_type_info * new_info; + switch (td->eTypeClass) + { + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + new_info = new JNI_compound_type_info( jni, td ); + break; + } + case typelib_TypeClass_INTERFACE: + { + new_info = new JNI_interface_type_info( jni, td ); + break; + } + default: + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("type info not supported for ") ); + buf.append( uno_name ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } + + // look up + JNI_type_info * info; + ClearableMutexGuard guard( m_mutex ); + JNI_type_info_holder & holder = m_type_map[ uno_name ]; + if (0 == holder.m_info) // new insertion + { + holder.m_info = new_info; + guard.clear(); + info = new_info; + } + else // inserted in the meantime + { + info = holder.m_info; + guard.clear(); + new_info->destroy( jni.get_jni_env() ); + } + return info; +} + +//______________________________________________________________________________ +JNI_type_info const * JNI_info::get_type_info( + JNI_context const & jni, typelib_TypeDescription * td ) const +{ + if (is_XInterface( td->pWeakRef )) + { + return m_XInterface_type_info; + } + + OUString const & uno_name = OUString::unacquired( &td->pTypeName ); + JNI_type_info const * info; + ClearableMutexGuard guard( m_mutex ); + + t_str2type::const_iterator iFind( m_type_map.find( uno_name ) ); + if (iFind == m_type_map.end()) + { + guard.clear(); + info = create_type_info( jni, td ); + } + else + { + info = iFind->second.m_info; + } + + return info; +} + +//______________________________________________________________________________ +JNI_type_info const * JNI_info::get_type_info( + JNI_context const & jni, typelib_TypeDescriptionReference * type ) const +{ + if (is_XInterface( type )) + { + return m_XInterface_type_info; + } + + OUString const & uno_name = OUString::unacquired( &type->pTypeName ); + JNI_type_info const * info; + ClearableMutexGuard guard( m_mutex ); + t_str2type::const_iterator iFind( m_type_map.find( uno_name ) ); + if (iFind == m_type_map.end()) + { + guard.clear(); + TypeDescr td( type ); + info = create_type_info( jni, td.get() ); + } + else + { + info = iFind->second.m_info; + } + + return info; +} + +//______________________________________________________________________________ +JNI_type_info const * JNI_info::get_type_info( + JNI_context const & jni, OUString const & uno_name ) const +{ + if (uno_name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) + { + return m_XInterface_type_info; + } + + JNI_type_info const * info; + ClearableMutexGuard guard( m_mutex ); + t_str2type::const_iterator iFind( m_type_map.find( uno_name ) ); + if (iFind == m_type_map.end()) + { + guard.clear(); + css::uno::TypeDescription td( uno_name ); + if (! td.is()) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("UNO type not found: ") ); + buf.append( uno_name ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + info = create_type_info( jni, td.get() ); + } + else + { + info = iFind->second.m_info; + } + + return info; +} + +//______________________________________________________________________________ +JNI_info::JNI_info( + JNIEnv * jni_env, jobject class_loader, jclass classClass, + jmethodID methodForName ) + : m_class_Class( classClass ), + m_method_Class_forName( methodForName ), + m_class_JNI_proxy( 0 ), + m_XInterface_queryInterface_td( + (reinterpret_cast< typelib_InterfaceTypeDescription * >( + css::uno::TypeDescription( + ::getCppuType( + (css::uno::Reference< css::uno::XInterface > const *)0 ) ) + .get())->ppMembers[ 0 ] ) ), + m_Exception_type( ::getCppuType( (css::uno::Exception const *)0 ) ), + m_RuntimeException_type( + ::getCppuType( (css::uno::RuntimeException const *)0 ) ), + m_void_type( ::getCppuVoidType() ), + m_XInterface_type_info( 0 ) +{ + JNI_context jni( this, jni_env, class_loader ); // !no proper jni_info! + + // class lookup + JLocalAutoRef jo_Object( + jni, find_class( jni, "java.lang.Object" ) ); + JLocalAutoRef jo_Class( + jni, find_class( jni, "java.lang.Class" ) ); + JLocalAutoRef jo_Throwable( + jni, find_class( jni, "java.lang.Throwable" ) ); + JLocalAutoRef jo_Character( + jni, find_class( jni, "java.lang.Character" ) ); + JLocalAutoRef jo_Boolean( + jni, find_class( jni, "java.lang.Boolean" ) ); + JLocalAutoRef jo_Byte( + jni, find_class( jni, "java.lang.Byte" ) ); + JLocalAutoRef jo_Short( + jni, find_class( jni, "java.lang.Short" ) ); + JLocalAutoRef jo_Integer( + jni, find_class( jni, "java.lang.Integer" ) ); + JLocalAutoRef jo_Long( + jni, find_class( jni, "java.lang.Long" ) ); + JLocalAutoRef jo_Float( + jni, find_class( jni, "java.lang.Float" ) ); + JLocalAutoRef jo_Double( + jni, find_class( jni, "java.lang.Double" ) ); + JLocalAutoRef jo_String( + jni, find_class( jni, "java.lang.String" ) ); + JLocalAutoRef jo_RuntimeException( + jni, find_class( jni, "com.sun.star.uno.RuntimeException" ) ); + JLocalAutoRef jo_UnoRuntime( + jni, find_class( jni, "com.sun.star.uno.UnoRuntime" ) ); + JLocalAutoRef jo_Any( + jni, find_class( jni, "com.sun.star.uno.Any" ) ); + JLocalAutoRef jo_Enum( + jni, find_class( jni, "com.sun.star.uno.Enum" ) ); + JLocalAutoRef jo_Type( + jni, find_class( jni, "com.sun.star.uno.Type" ) ); + JLocalAutoRef jo_TypeClass( + jni, find_class( jni, "com.sun.star.uno.TypeClass" ) ); + JLocalAutoRef jo_IEnvironment( + jni, find_class( jni, "com.sun.star.uno.IEnvironment" ) ); + JLocalAutoRef jo_JNI_proxy( + jni, find_class( jni, "com.sun.star.bridges.jni_uno.JNI_proxy" ) ); + + // method Object.toString() + m_method_Object_toString = jni->GetMethodID( + (jclass) jo_Object.get(), "toString", "()Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Object_toString ); + // method Class.getName() + m_method_Class_getName = jni->GetMethodID( + (jclass) jo_Class.get(), "getName", "()Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Class_getName ); + + // method Throwable.getMessage() + m_method_Throwable_getMessage = jni->GetMethodID( + (jclass) jo_Throwable.get(), "getMessage", "()Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Throwable_getMessage ); + + // method Character.charValue() + m_method_Character_charValue = jni->GetMethodID( + (jclass) jo_Character.get(), "charValue", "()C" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Character_charValue ); + // method Boolean.booleanValue() + m_method_Boolean_booleanValue = jni->GetMethodID( + (jclass) jo_Boolean.get(), "booleanValue", "()Z" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Boolean_booleanValue ); + // method Byte.byteValue() + m_method_Byte_byteValue = jni->GetMethodID( + (jclass) jo_Byte.get(), "byteValue", "()B" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Byte_byteValue ); + // method Short.shortValue() + m_method_Short_shortValue = jni->GetMethodID( + (jclass) jo_Short.get(), "shortValue", "()S" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Short_shortValue ); + // method Integer.intValue() + m_method_Integer_intValue = jni->GetMethodID( + (jclass) jo_Integer.get(), "intValue", "()I" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Integer_intValue ); + // method Long.longValue() + m_method_Long_longValue = jni->GetMethodID( + (jclass) jo_Long.get(), "longValue", "()J" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Long_longValue ); + // method Float.floatValue() + m_method_Float_floatValue = jni->GetMethodID( + (jclass) jo_Float.get(), "floatValue", "()F" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Float_floatValue ); + // method Double.doubleValue() + m_method_Double_doubleValue = jni->GetMethodID( + (jclass) jo_Double.get(), "doubleValue", "()D" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_Double_doubleValue ); + + // ctor Character( char ) + m_ctor_Character_with_char = jni->GetMethodID( + (jclass) jo_Character.get(), "<init>", "(C)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Character_with_char ); + // ctor Boolean( boolean ) + m_ctor_Boolean_with_boolean = jni->GetMethodID( + (jclass) jo_Boolean.get(), "<init>", "(Z)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Boolean_with_boolean ); + // ctor Byte( byte ) + m_ctor_Byte_with_byte = jni->GetMethodID( + (jclass) jo_Byte.get(), "<init>", "(B)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Byte_with_byte ); + // ctor Short( short ) + m_ctor_Short_with_short = jni->GetMethodID( + (jclass) jo_Short.get(), "<init>", "(S)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Short_with_short ); + // ctor Integer( int ) + m_ctor_Integer_with_int = jni->GetMethodID( + (jclass) jo_Integer.get(), "<init>", "(I)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Integer_with_int ); + // ctor Long( long ) + m_ctor_Long_with_long = jni->GetMethodID( + (jclass) jo_Long.get(), "<init>", "(J)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Long_with_long ); + // ctor Float( float ) + m_ctor_Float_with_float = jni->GetMethodID( + (jclass) jo_Float.get(), "<init>", "(F)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Float_with_float ); + // ctor Double( double ) + m_ctor_Double_with_double = jni->GetMethodID( + (jclass) jo_Double.get(), "<init>", "(D)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Double_with_double ); + + // static method UnoRuntime.generateOid() + m_method_UnoRuntime_generateOid = jni->GetStaticMethodID( + (jclass) jo_UnoRuntime.get(), + "generateOid", "(Ljava/lang/Object;)Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_UnoRuntime_generateOid ); + // static method UnoRuntime.queryInterface() + m_method_UnoRuntime_queryInterface = jni->GetStaticMethodID( + (jclass) jo_UnoRuntime.get(), + "queryInterface", + "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_UnoRuntime_queryInterface ); + + // field Enum.m_value + m_field_Enum_m_value = jni->GetFieldID( + (jclass) jo_Enum.get(), "m_value", "I" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_Enum_m_value ); + + // static method TypeClass.fromInt() + m_method_TypeClass_fromInt = jni->GetStaticMethodID( + (jclass) jo_TypeClass.get(), + "fromInt", "(I)Lcom/sun/star/uno/TypeClass;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_TypeClass_fromInt ); + + // ctor Type( Class ) + m_ctor_Type_with_Class = jni->GetMethodID( + (jclass) jo_Type.get(), "<init>", "(Ljava/lang/Class;)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Type_with_Class ); + // ctor Type( String, TypeClass ) + m_ctor_Type_with_Name_TypeClass = jni->GetMethodID( + (jclass) jo_Type.get(), + "<init>", "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Type_with_Name_TypeClass ); + // field Type._typeName + m_field_Type__typeName = jni->GetFieldID( + (jclass) jo_Type.get(), "_typeName", "Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_Type__typeName ); + + // ctor Any( Type, Object ) + m_ctor_Any_with_Type_Object = jni->GetMethodID( + (jclass) jo_Any.get(), + "<init>", "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_ctor_Any_with_Type_Object ); + + // field Any._type + m_field_Any__type = jni->GetFieldID( + (jclass) jo_Any.get(), "_type", "Lcom/sun/star/uno/Type;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_Any__type ); + // field Any._object + m_field_Any__object = jni->GetFieldID( + (jclass) jo_Any.get(), "_object", "Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_Any__object ); + + // method IEnvironment.getRegisteredInterface() + m_method_IEnvironment_getRegisteredInterface = jni->GetMethodID( + (jclass) jo_IEnvironment.get(), + "getRegisteredInterface", + "(Ljava/lang/String;Lcom/sun/star/uno/Type;)Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_IEnvironment_getRegisteredInterface ); + // method IEnvironment.registerInterface() + m_method_IEnvironment_registerInterface = jni->GetMethodID( + (jclass) jo_IEnvironment.get(), "registerInterface", + "(Ljava/lang/Object;[Ljava/lang/String;Lcom/sun/star/uno/Type;)" + "Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_IEnvironment_registerInterface ); + + // static method JNI_proxy.get_proxy_ctor() + m_method_JNI_proxy_get_proxy_ctor = jni->GetStaticMethodID( + (jclass) jo_JNI_proxy.get(), "get_proxy_ctor", + "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_JNI_proxy_get_proxy_ctor ); + // static method JNI_proxy.create() + m_method_JNI_proxy_create = jni->GetStaticMethodID( + (jclass) jo_JNI_proxy.get(), "create", + "(JLcom/sun/star/uno/IEnvironment;JJLcom/sun/star/uno/Type;Ljava/lang" + "/String;Ljava/lang/reflect/Constructor;)Ljava/lang/Object;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_method_JNI_proxy_create ); + // field JNI_proxy.m_receiver_handle + m_field_JNI_proxy_m_receiver_handle = jni->GetFieldID( + (jclass) jo_JNI_proxy.get(), "m_receiver_handle", "J" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_JNI_proxy_m_receiver_handle ); + // field JNI_proxy.m_td_handle + m_field_JNI_proxy_m_td_handle = jni->GetFieldID( + (jclass) jo_JNI_proxy.get(), "m_td_handle", "J" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_JNI_proxy_m_td_handle ); + // field JNI_proxy.m_type + m_field_JNI_proxy_m_type = jni->GetFieldID( + (jclass) jo_JNI_proxy.get(), "m_type", "Lcom/sun/star/uno/Type;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_JNI_proxy_m_type ); + // field JNI_proxy.m_oid + m_field_JNI_proxy_m_oid = jni->GetFieldID( + (jclass) jo_JNI_proxy.get(), "m_oid", "Ljava/lang/String;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != m_field_JNI_proxy_m_oid ); + + // get java env + OUString java_env_type_name( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_JAVA) ); + JLocalAutoRef jo_java( + jni, ustring_to_jstring( jni, java_env_type_name.pData ) ); + jvalue args[ 2 ]; + args[ 0 ].l = jo_java.get(); + args[ 1 ].l = 0; + jmethodID method_getEnvironment = jni->GetStaticMethodID( + (jclass) jo_UnoRuntime.get(), "getEnvironment", + "(Ljava/lang/String;Ljava/lang/Object;)" + "Lcom/sun/star/uno/IEnvironment;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != method_getEnvironment ); + JLocalAutoRef jo_java_env( + jni, jni->CallStaticObjectMethodA( + (jclass) jo_UnoRuntime.get(), method_getEnvironment, args ) ); + + // get com.sun.star.uno.Any.VOID + jfieldID field_Any_VOID = jni->GetStaticFieldID( + (jclass) jo_Any.get(), "VOID", "Lcom/sun/star/uno/Any;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != field_Any_VOID ); + JLocalAutoRef jo_Any_VOID( + jni, jni->GetStaticObjectField( + (jclass) jo_Any.get(), field_Any_VOID ) ); + // get com.sun.star.uno.Type.UNSIGNED_SHORT + jfieldID field_Type_UNSIGNED_SHORT = jni->GetStaticFieldID( + (jclass) jo_Type.get(), "UNSIGNED_SHORT", "Lcom/sun/star/uno/Type;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != field_Type_UNSIGNED_SHORT ); + JLocalAutoRef jo_Type_UNSIGNED_SHORT( + jni, jni->GetStaticObjectField( + (jclass) jo_Type.get(), field_Type_UNSIGNED_SHORT ) ); + // get com.sun.star.uno.Type.UNSIGNED_LONG + jfieldID field_Type_UNSIGNED_LONG = jni->GetStaticFieldID( + (jclass) jo_Type.get(), "UNSIGNED_LONG", "Lcom/sun/star/uno/Type;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != field_Type_UNSIGNED_LONG ); + JLocalAutoRef jo_Type_UNSIGNED_LONG( + jni, jni->GetStaticObjectField( + (jclass) jo_Type.get(), field_Type_UNSIGNED_LONG ) ); + // get com.sun.star.uno.Type.UNSIGNED_HYPER + jfieldID field_Type_UNSIGNED_HYPER = jni->GetStaticFieldID( + (jclass) jo_Type.get(), "UNSIGNED_HYPER", "Lcom/sun/star/uno/Type;" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != field_Type_UNSIGNED_HYPER ); + JLocalAutoRef jo_Type_UNSIGNED_HYPER( + jni, jni->GetStaticObjectField( + (jclass) jo_Type.get(), field_Type_UNSIGNED_HYPER ) ); + + // make global refs + m_class_UnoRuntime = + (jclass) jni->NewGlobalRef( jo_UnoRuntime.get() ); + m_class_RuntimeException = + (jclass) jni->NewGlobalRef( jo_RuntimeException.get() ); + m_class_Any = + (jclass) jni->NewGlobalRef( jo_Any.get() ); + m_class_Type = + (jclass) jni->NewGlobalRef( jo_Type.get() ); + m_class_TypeClass = + (jclass) jni->NewGlobalRef( jo_TypeClass.get() ); + m_class_JNI_proxy = + (jclass) jni->NewGlobalRef( jo_JNI_proxy.get() ); + + m_class_Character = + (jclass) jni->NewGlobalRef( jo_Character.get() ); + m_class_Boolean = + (jclass) jni->NewGlobalRef( jo_Boolean.get() ); + m_class_Byte = + (jclass) jni->NewGlobalRef( jo_Byte.get() ); + m_class_Short = + (jclass) jni->NewGlobalRef( jo_Short.get() ); + m_class_Integer = + (jclass) jni->NewGlobalRef( jo_Integer.get() ); + m_class_Long = + (jclass) jni->NewGlobalRef( jo_Long.get() ); + m_class_Float = + (jclass) jni->NewGlobalRef( jo_Float.get() ); + m_class_Double = + (jclass) jni->NewGlobalRef( jo_Double.get() ); + m_class_String = + (jclass) jni->NewGlobalRef( jo_String.get() ); + m_class_Object = + (jclass) jni->NewGlobalRef( jo_Object.get() ); + m_class_Class = + (jclass) jni->NewGlobalRef( m_class_Class ); + + m_object_Any_VOID = + jni->NewGlobalRef( jo_Any_VOID.get() ); + m_object_Type_UNSIGNED_SHORT = + jni->NewGlobalRef( jo_Type_UNSIGNED_SHORT.get() ); + m_object_Type_UNSIGNED_LONG = + jni->NewGlobalRef( jo_Type_UNSIGNED_LONG.get() ); + m_object_Type_UNSIGNED_HYPER = + jni->NewGlobalRef( jo_Type_UNSIGNED_HYPER.get() ); + m_object_java_env = jni->NewGlobalRef( jo_java_env.get() ); + + try + { + css::uno::TypeDescription XInterface_td( + ::getCppuType( + (css::uno::Reference< css::uno::XInterface > const *)0 ) ); + m_XInterface_type_info = + new JNI_interface_type_info( jni, XInterface_td.get() ); + } + catch (...) + { + destruct( jni_env ); + throw; + } +} + +//______________________________________________________________________________ +void JNI_info::destruct( JNIEnv * jni_env ) +{ + t_str2type::const_iterator iPos( m_type_map.begin() ); + t_str2type::const_iterator const iEnd( m_type_map.begin() ); + for ( ; iPos != iEnd; ++iPos ) + { + iPos->second.m_info->destroy( jni_env ); + } + if (0 != m_XInterface_type_info) + { + const_cast< JNI_interface_type_info * >( + m_XInterface_type_info )->destroy( jni_env ); + } + + // free global refs + jni_env->DeleteGlobalRef( m_object_java_env ); + jni_env->DeleteGlobalRef( m_object_Any_VOID ); + jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_SHORT ); + jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_LONG ); + jni_env->DeleteGlobalRef( m_object_Type_UNSIGNED_HYPER ); + + jni_env->DeleteGlobalRef( m_class_Class ); + jni_env->DeleteGlobalRef( m_class_Object ); + jni_env->DeleteGlobalRef( m_class_String ); + jni_env->DeleteGlobalRef( m_class_Double ); + jni_env->DeleteGlobalRef( m_class_Float ); + jni_env->DeleteGlobalRef( m_class_Long ); + jni_env->DeleteGlobalRef( m_class_Integer ); + jni_env->DeleteGlobalRef( m_class_Short ); + jni_env->DeleteGlobalRef( m_class_Byte ); + jni_env->DeleteGlobalRef( m_class_Boolean ); + jni_env->DeleteGlobalRef( m_class_Character ); + + jni_env->DeleteGlobalRef( m_class_JNI_proxy ); + jni_env->DeleteGlobalRef( m_class_RuntimeException ); + jni_env->DeleteGlobalRef( m_class_UnoRuntime ); + jni_env->DeleteGlobalRef( m_class_TypeClass ); + jni_env->DeleteGlobalRef( m_class_Type ); + jni_env->DeleteGlobalRef( m_class_Any ); +} + +//______________________________________________________________________________ +JNI_info const * JNI_info::get_jni_info( + rtl::Reference< jvmaccess::UnoVirtualMachine > const & uno_vm ) +{ + // !!!no JNI_info available at JNI_context!!! + ::jvmaccess::VirtualMachine::AttachGuard guard( + uno_vm->getVirtualMachine() ); + JNIEnv * jni_env = guard.getEnvironment(); + JNI_context jni( + 0, jni_env, static_cast< jobject >(uno_vm->getClassLoader()) ); + + jclass jo_class; + jmethodID jo_forName; + jni.getClassForName( &jo_class, &jo_forName ); + jni.ensure_no_exception(); + JLocalAutoRef jo_JNI_info_holder( + jni, + jni.findClass( + "com.sun.star.bridges.jni_uno.JNI_info_holder", jo_class, + jo_forName, false ) ); + // field JNI_info_holder.m_jni_info_handle + jfieldID field_s_jni_info_handle = + jni->GetStaticFieldID( + (jclass) jo_JNI_info_holder.get(), "s_jni_info_handle", "J" ); + jni.ensure_no_exception(); + OSL_ASSERT( 0 != field_s_jni_info_handle ); + + JNI_info const * jni_info = + reinterpret_cast< JNI_info const * >( + jni->GetStaticLongField( + (jclass) jo_JNI_info_holder.get(), field_s_jni_info_handle ) ); + if (0 == jni_info) // un-initialized? + { + JNI_info * new_info = new JNI_info( + jni_env, static_cast< jobject >(uno_vm->getClassLoader()), jo_class, + jo_forName ); + + ClearableMutexGuard g( Mutex::getGlobalMutex() ); + jni_info = + reinterpret_cast< JNI_info const * >( + jni->GetStaticLongField( + (jclass) jo_JNI_info_holder.get(), + field_s_jni_info_handle ) ); + if (0 == jni_info) // still un-initialized? + { + jni->SetStaticLongField( + (jclass) jo_JNI_info_holder.get(), field_s_jni_info_handle, + reinterpret_cast< jlong >( new_info ) ); + jni_info = new_info; + } + else + { + g.clear(); + new_info->destroy( jni_env ); + } + } + + return jni_info; +} + +} + +extern "C" +{ + +//------------------------------------------------------------------------------ +JNIEXPORT void +JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1info_1holder_finalize__J( + JNIEnv * jni_env, jobject, jlong jni_info_handle ) + SAL_THROW_EXTERN_C() +{ + ::jni_uno::JNI_info * jni_info = + reinterpret_cast< ::jni_uno::JNI_info * >( jni_info_handle ); + jni_info->destroy( jni_env ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_info.h b/bridges/source/jni_uno/jni_info.h new file mode 100644 index 000000000000..a356be272e04 --- /dev/null +++ b/bridges/source/jni_uno/jni_info.h @@ -0,0 +1,378 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_JNI_INFO_H +#define INCLUDED_JNI_INFO_H + +#include <boost/unordered_map.hpp> + +#include "jni_base.h" + +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "rtl/strbuf.hxx" + +#include "uno/environment.h" +#include "typelib/typedescription.hxx" + +#include "com/sun/star/uno/Type.hxx" + +namespace jvmaccess { class UnoVirtualMachine; } + +namespace jni_uno +{ + +//------------------------------------------------------------------------------ +inline bool type_equals( + typelib_TypeDescriptionReference * type1, + typelib_TypeDescriptionReference * type2 ) +{ + if (type1 == type2) + return true; + ::rtl::OUString const & name1 = + ::rtl::OUString::unacquired( &type1->pTypeName ); + ::rtl::OUString const & name2 = + ::rtl::OUString::unacquired( &type2->pTypeName ); + return ((type1->eTypeClass == type2->eTypeClass) && name1.equals( name2 )); +} + +//------------------------------------------------------------------------------ +inline bool is_XInterface( typelib_TypeDescriptionReference * type ) +{ + return ((typelib_TypeClass_INTERFACE == type->eTypeClass) && + ::rtl::OUString::unacquired( &type->pTypeName ).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )); +} + +//============================================================================== +struct JNI_type_info +{ + ::com::sun::star::uno::TypeDescription m_td; + jclass m_class; + + virtual void destroy( JNIEnv * jni_env ) = 0; +protected: + inline void destruct( JNIEnv * jni_env ) + { jni_env->DeleteGlobalRef( m_class ); } + virtual inline ~JNI_type_info() {} + explicit JNI_type_info( + JNI_context const & jni, typelib_TypeDescription * td ); +}; + +//============================================================================== +struct JNI_interface_type_info : public JNI_type_info +{ + jobject m_proxy_ctor; // proxy ctor + jobject m_type; + // sorted via typelib function index + jmethodID * m_methods; + + virtual void destroy( JNIEnv * jni_env ); + explicit JNI_interface_type_info( + JNI_context const & jni, typelib_TypeDescription * td ); +}; + +//============================================================================== +struct JNI_compound_type_info : public JNI_type_info +{ + JNI_type_info const * m_base; + // ctor( msg ) for exceptions + jmethodID m_exc_ctor; + // sorted via typelib member index + jfieldID * m_fields; + + virtual void destroy( JNIEnv * jni_env ); + explicit JNI_compound_type_info( + JNI_context const & jni, typelib_TypeDescription * td ); +}; + +//============================================================================== +struct JNI_type_info_holder +{ + JNI_type_info * m_info; + inline JNI_type_info_holder() + : m_info( 0 ) + {} +}; + +typedef ::boost::unordered_map< + ::rtl::OUString, JNI_type_info_holder, ::rtl::OUStringHash > t_str2type; + +//============================================================================== +class JNI_info +{ + mutable ::osl::Mutex m_mutex; + mutable t_str2type m_type_map; + +public: + // These two are needed very early by find_class from within the ctor: + jclass m_class_Class; + jmethodID m_method_Class_forName; + + // + jobject m_object_java_env; + jobject m_object_Any_VOID; + jobject m_object_Type_UNSIGNED_SHORT; + jobject m_object_Type_UNSIGNED_LONG; + jobject m_object_Type_UNSIGNED_HYPER; + + // + jclass m_class_Object; + jclass m_class_Character; + jclass m_class_Boolean; + jclass m_class_Byte; + jclass m_class_Short; + jclass m_class_Integer; + jclass m_class_Long; + jclass m_class_Float; + jclass m_class_Double; + jclass m_class_String; + + jclass m_class_UnoRuntime; + jclass m_class_RuntimeException; + jclass m_class_Any; + jclass m_class_Type; + jclass m_class_TypeClass; + jclass m_class_JNI_proxy; + + // + jmethodID m_method_Object_toString; + jmethodID m_method_Class_getName; + jmethodID m_method_Throwable_getMessage; + jmethodID m_ctor_Character_with_char; + jmethodID m_ctor_Boolean_with_boolean; + jmethodID m_ctor_Byte_with_byte; + jmethodID m_ctor_Short_with_short; + jmethodID m_ctor_Integer_with_int; + jmethodID m_ctor_Long_with_long; + jmethodID m_ctor_Float_with_float; + jmethodID m_ctor_Double_with_double; + jmethodID m_method_Boolean_booleanValue; + jmethodID m_method_Byte_byteValue; + jmethodID m_method_Character_charValue; + jmethodID m_method_Double_doubleValue; + jmethodID m_method_Float_floatValue; + jmethodID m_method_Integer_intValue; + jmethodID m_method_Long_longValue; + jmethodID m_method_Short_shortValue; + + // + jmethodID m_method_IEnvironment_getRegisteredInterface; + jmethodID m_method_IEnvironment_registerInterface; + jmethodID m_method_UnoRuntime_generateOid; + jmethodID m_method_UnoRuntime_queryInterface; + jmethodID m_ctor_Any_with_Type_Object; + jfieldID m_field_Any__type; + jfieldID m_field_Any__object; + jmethodID m_ctor_Type_with_Class; + jmethodID m_ctor_Type_with_Name_TypeClass; + jfieldID m_field_Type__typeName; + jmethodID m_method_TypeClass_fromInt; + jfieldID m_field_Enum_m_value; + + // + jmethodID m_method_JNI_proxy_get_proxy_ctor; + jmethodID m_method_JNI_proxy_create; + jfieldID m_field_JNI_proxy_m_receiver_handle; + jfieldID m_field_JNI_proxy_m_td_handle; + jfieldID m_field_JNI_proxy_m_type; + jfieldID m_field_JNI_proxy_m_oid; + + // + ::com::sun::star::uno::TypeDescription m_XInterface_queryInterface_td; + ::com::sun::star::uno::Type const & m_Exception_type; + ::com::sun::star::uno::Type const & m_RuntimeException_type; + ::com::sun::star::uno::Type const & m_void_type; + // + JNI_interface_type_info const * m_XInterface_type_info; + + // + JNI_type_info const * get_type_info( + JNI_context const & jni, + typelib_TypeDescription * type ) const; + JNI_type_info const * get_type_info( + JNI_context const & jni, + typelib_TypeDescriptionReference * type ) const; + JNI_type_info const * get_type_info( + JNI_context const & jni, + ::rtl::OUString const & uno_name ) const; + // + inline static void append_sig( + ::rtl::OStringBuffer * buf, typelib_TypeDescriptionReference * type, + bool use_Object_for_type_XInterface = true, bool use_slashes = true ); + + // get this + static JNI_info const * get_jni_info( + rtl::Reference< jvmaccess::UnoVirtualMachine > const & uno_vm ); + inline void destroy( JNIEnv * jni_env ); + +private: + JNI_type_info const * create_type_info( + JNI_context const & jni, typelib_TypeDescription * td ) const; + + void destruct( JNIEnv * jni_env ); + + JNI_info( JNIEnv * jni_env, jobject class_loader, + jclass classClass, jmethodID methodForName ); + inline ~JNI_info() {} +}; + +//______________________________________________________________________________ +inline void JNI_info::destroy( JNIEnv * jni_env ) +{ + destruct( jni_env ); + delete this; +} + +//______________________________________________________________________________ +inline void JNI_info::append_sig( + ::rtl::OStringBuffer * buf, typelib_TypeDescriptionReference * type, + bool use_Object_for_type_XInterface, bool use_slashes ) +{ + switch (type->eTypeClass) + { + case typelib_TypeClass_VOID: + buf->append( 'V' ); + break; + case typelib_TypeClass_CHAR: + buf->append( 'C' ); + break; + case typelib_TypeClass_BOOLEAN: + buf->append( 'Z' ); + break; + case typelib_TypeClass_BYTE: + buf->append( 'B' ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + buf->append( 'S' ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + buf->append( 'I' ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + buf->append( 'J' ); + break; + case typelib_TypeClass_FLOAT: + buf->append( 'F' ); + break; + case typelib_TypeClass_DOUBLE: + buf->append( 'D' ); + break; + case typelib_TypeClass_STRING: + if ( use_slashes ) { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;") ); + } else { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.String;") ); + } + break; + case typelib_TypeClass_TYPE: + if ( use_slashes ) { + buf->append( + RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;") ); + } else { + buf->append( + RTL_CONSTASCII_STRINGPARAM("Lcom.sun.star.uno.Type;") ); + } + break; + case typelib_TypeClass_ANY: + if ( use_slashes ) { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;") ); + } else { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.Object;") ); + } + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + ::rtl::OUString const & uno_name = + ::rtl::OUString::unacquired( &type->pTypeName ); + buf->append( 'L' ); + // Erase type arguments of instantiated polymorphic struct types: + sal_Int32 i = uno_name.indexOf( '<' ); + if ( i < 0 ) { + buf->append( + ::rtl::OUStringToOString( + use_slashes ? uno_name.replace( '.', '/' ) : uno_name, + RTL_TEXTENCODING_JAVA_UTF8 ) ); + } else { + rtl::OUString s( uno_name.copy( 0, i ) ); + buf->append( + ::rtl::OUStringToOString( + use_slashes ? s.replace( '.', '/' ) : s, + RTL_TEXTENCODING_JAVA_UTF8 ) ); + } + buf->append( ';' ); + break; + } + case typelib_TypeClass_SEQUENCE: + { + buf->append( '[' ); + TypeDescr td( type ); + append_sig( + buf, ((typelib_IndirectTypeDescription *)td.get())->pType, + use_Object_for_type_XInterface, use_slashes ); + break; + } + case typelib_TypeClass_INTERFACE: + if (use_Object_for_type_XInterface && is_XInterface( type )) + { + if ( use_slashes ) { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;") ); + } else { + buf->append( RTL_CONSTASCII_STRINGPARAM("Ljava.lang.Object;") ); + } + } + else + { + ::rtl::OUString const & uno_name = + ::rtl::OUString::unacquired( &type->pTypeName ); + buf->append( 'L' ); + buf->append( + ::rtl::OUStringToOString( + use_slashes ? uno_name.replace( '.', '/' ) : uno_name, + RTL_TEXTENCODING_JAVA_UTF8 ) ); + buf->append( ';' ); + } + break; + default: + throw BridgeRuntimeError( + OUSTR("unsupported type: ") + + ::rtl::OUString::unacquired( &type->pTypeName ) ); + } +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_java2uno.cxx b/bridges/source/jni_uno/jni_java2uno.cxx new file mode 100644 index 000000000000..63a9c0ad02ac --- /dev/null +++ b/bridges/source/jni_uno/jni_java2uno.cxx @@ -0,0 +1,706 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include "jni_bridge.h" + +#include <rtl/ustrbuf.hxx> + +#include <algorithm> + + +using namespace ::rtl; + +namespace jni_uno +{ + +//______________________________________________________________________________ +jobject Bridge::map_to_java( + JNI_context const & jni, + uno_Interface * pUnoI, JNI_interface_type_info const * info ) const +{ + // get oid + rtl_uString * pOid = 0; + (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI ); + OSL_ASSERT( 0 != pOid ); + OUString oid( pOid, SAL_NO_ACQUIRE ); + + // opt getRegisteredInterface() + JLocalAutoRef jo_oid( jni, ustring_to_jstring( jni, oid.pData ) ); + jvalue args[ 2 ]; + args[ 0 ].l = jo_oid.get(); + args[ 1 ].l = info->m_type; + jobject jo_iface = jni->CallObjectMethodA( + m_jni_info->m_object_java_env, + m_jni_info->m_method_IEnvironment_getRegisteredInterface, args ); + jni.ensure_no_exception(); + + if (0 == jo_iface) // no registered iface + { + // register uno interface + (*m_uno_env->registerInterface)( + m_uno_env, reinterpret_cast< void ** >( &pUnoI ), + oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); + + // create java and register java proxy + jvalue args2[ 7 ]; + acquire(); + args2[ 0 ].j = reinterpret_cast< sal_Int64 >( this ); + (*pUnoI->acquire)( pUnoI ); + args2[ 1 ].l = m_jni_info->m_object_java_env; + args2[ 2 ].j = reinterpret_cast< sal_Int64 >( pUnoI ); + typelib_typedescription_acquire( info->m_td.get() ); + args2[ 3 ].j = reinterpret_cast< sal_Int64 >( info->m_td.get() ); + args2[ 4 ].l = info->m_type; + args2[ 5 ].l = jo_oid.get(); + args2[ 6 ].l = info->m_proxy_ctor; + jo_iface = jni->CallStaticObjectMethodA( + m_jni_info->m_class_JNI_proxy, + m_jni_info->m_method_JNI_proxy_create, args2 ); + jni.ensure_no_exception(); + } + + OSL_ASSERT( 0 != jo_iface ); + return jo_iface; +} + + +//______________________________________________________________________________ +void Bridge::handle_uno_exc( JNI_context const & jni, uno_Any * uno_exc ) const +{ + if (typelib_TypeClass_EXCEPTION == uno_exc->pType->eTypeClass) + { +#if OSL_DEBUG_LEVEL > 0 + // append java stack trace to Message member + reinterpret_cast< ::com::sun::star::uno::Exception * >( + uno_exc->pData )->Message += jni.get_stack_trace(); +#endif + +#if OSL_DEBUG_LEVEL > 1 + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("exception occurred java->uno: [") ); + buf.append( OUString::unacquired( &uno_exc->pType->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + buf.append( + reinterpret_cast< ::com::sun::star::uno::Exception const * >( + uno_exc->pData )->Message ); + OString cstr_msg( + OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg.getStr() ); + } +#endif + // signal exception + jvalue java_exc; + try + { + map_to_java( + jni, &java_exc, uno_exc->pData, uno_exc->pType, 0, + true /* in */, false /* no out */ ); + } + catch (...) + { + uno_any_destruct( uno_exc, 0 ); + throw; + } + uno_any_destruct( uno_exc, 0 ); + + JLocalAutoRef jo_exc( jni, java_exc.l ); + jint res = jni->Throw( (jthrowable) jo_exc.get() ); + if (0 != res) + { + // call toString() + JLocalAutoRef jo_descr( + jni, jni->CallObjectMethodA( + jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "throwing java exception failed: ") ); + buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + } + else + { + OUString message( + OUSTR("thrown exception is no uno exception: ") + + OUString::unacquired( &uno_exc->pType->pTypeName ) + + jni.get_stack_trace() ); + uno_any_destruct( uno_exc, 0 ); + throw BridgeRuntimeError( message ); + } +} + +union largest +{ + sal_Int64 n; + double d; + void * p; + uno_Any a; +}; + +//______________________________________________________________________________ +jobject Bridge::call_uno( + JNI_context const & jni, + uno_Interface * pUnoI, typelib_TypeDescription * member_td, + typelib_TypeDescriptionReference * return_type, + sal_Int32 nParams, typelib_MethodParameter const * pParams, + jobjectArray jo_args /* may be 0 */ ) const +{ + // return mem + sal_Int32 return_size; + switch (return_type->eTypeClass) { + case typelib_TypeClass_VOID: + return_size = 0; + break; + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + return_size = std::max( + TypeDescr(return_type).get()->nSize, + static_cast< sal_Int32 >(sizeof (largest))); + break; + + default: + return_size = sizeof (largest); + break; + } + +#ifdef BROKEN_ALLOCA + char * mem = (char *) malloc( +#else + char * mem = (char *) alloca( +#endif + (nParams * sizeof (void *)) + + return_size + (nParams * sizeof (largest)) ); + void ** uno_args = (void **) mem; + void * uno_ret = return_size == 0 ? 0 : (mem + (nParams * sizeof (void *))); + largest * uno_args_mem = (largest *) + (mem + (nParams * sizeof (void *)) + return_size); + + OSL_ASSERT( (0 == nParams) || (nParams == jni->GetArrayLength( jo_args )) ); + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & param = pParams[ nPos ]; + typelib_TypeDescriptionReference * type = param.pTypeRef; + + uno_args[ nPos ] = &uno_args_mem[ nPos ]; + if (typelib_TypeClass_STRUCT == type->eTypeClass || + typelib_TypeClass_EXCEPTION == type->eTypeClass) + { + TypeDescr td( type ); + if (sal::static_int_cast< sal_uInt32 >(td.get()->nSize) + > sizeof (largest)) +#ifdef BROKEN_ALLOCA + uno_args[ nPos ] = malloc( td.get()->nSize ); +#else + uno_args[ nPos ] = alloca( td.get()->nSize ); +#endif + } + + if (param.bIn) + { + try + { + JLocalAutoRef jo_arg( + jni, jni->GetObjectArrayElement( jo_args, nPos ) ); + jni.ensure_no_exception(); + jvalue java_arg; + java_arg.l = jo_arg.get(); + map_to_uno( + jni, uno_args[ nPos ], java_arg, type, 0, + false /* no assign */, sal_False != param.bOut, + true /* special wrapped integral types */ ); + } + catch (...) + { + // cleanup uno in args + for ( sal_Int32 n = 0; n < nPos; ++n ) + { + typelib_MethodParameter const & p = pParams[ n ]; + if (p.bIn) + { + uno_type_destructData( + uno_args[ n ], p.pTypeRef, 0 ); + } +#ifdef BROKEN_ALLOCA + if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) + free( uno_args[ nPos ] ); +#endif + } +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + throw; + } + } + } + + uno_Any uno_exc_holder; + uno_Any * uno_exc = &uno_exc_holder; + // call binary uno + (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc ); + + if (0 == uno_exc) + { + // convert out args; destruct uno args + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & param = pParams[ nPos ]; + typelib_TypeDescriptionReference * type = param.pTypeRef; + if (param.bOut) + { + try + { + // get out holder array[ 1 ] + JLocalAutoRef jo_out_holder( + jni, jni->GetObjectArrayElement( jo_args, nPos ) ); + jni.ensure_no_exception(); + jvalue java_arg; + java_arg.l = jo_out_holder.get(); + map_to_java( + jni, &java_arg, uno_args[ nPos ], type, 0, + true /* in */, true /* out holder */ ); + } + catch (...) + { + // cleanup further uno args + for ( sal_Int32 n = nPos; n < nParams; ++n ) + { + uno_type_destructData( + uno_args[ n ], pParams[ n ].pTypeRef, 0 ); +#ifdef BROKEN_ALLOCA + if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) + free( uno_args[ nPos ] ); +#endif + } + // cleanup uno return value + uno_type_destructData( uno_ret, return_type, 0 ); +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + throw; + } + } + if (typelib_TypeClass_DOUBLE < type->eTypeClass && + typelib_TypeClass_ENUM != type->eTypeClass) // opt + { + uno_type_destructData( uno_args[ nPos ], type, 0 ); +#ifdef BROKEN_ALLOCA + if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) + free( uno_args[ nPos ] ); +#endif + } + } + + if (typelib_TypeClass_VOID != return_type->eTypeClass) + { + // convert uno return value + jvalue java_ret; + try + { + map_to_java( + jni, &java_ret, uno_ret, return_type, 0, + true /* in */, false /* no out */, + true /* special_wrapped_integral_types */ ); + } + catch (...) + { + uno_type_destructData( uno_ret, return_type, 0 ); +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + throw; + } + if (typelib_TypeClass_DOUBLE < return_type->eTypeClass && + typelib_TypeClass_ENUM != return_type->eTypeClass) // opt + { + uno_type_destructData( uno_ret, return_type, 0 ); + } +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + return java_ret.l; + } +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + return 0; // void return + } + else // exception occurred + { + // destruct uno in args + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & param = pParams[ nPos ]; + if (param.bIn) + uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 ); +#ifdef BROKEN_ALLOCA + if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) + free( uno_args[ nPos ] ); +#endif + } + + handle_uno_exc( jni, uno_exc ); +#ifdef BROKEN_ALLOCA + free( mem ); +#endif + return 0; + } +} + +} + +using namespace ::jni_uno; + +extern "C" +{ + +//------------------------------------------------------------------------------ +JNIEXPORT jobject +JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call( + JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle, jstring, + jstring jo_method, jobjectArray jo_args /* may be 0 */ ) + SAL_THROW_EXTERN_C() +{ + Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle ); + JNI_info const * jni_info = bridge->m_jni_info; + JNI_context jni( + jni_info, jni_env, + static_cast< jobject >( + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext )->getClassLoader() ) ); + + OUString method_name; + + try + { + method_name = jstring_to_oustring( jni, jo_method ); +#if OSL_DEBUG_LEVEL > 1 + { + OUStringBuffer trace_buf( 64 ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("java->uno call: ") ); + trace_buf.append( method_name ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") ); + JLocalAutoRef jo_oid( + jni, jni->GetObjectField( + jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); + trace_buf.append( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); + OString cstr_msg( + OUStringToOString( + trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg.getStr() ); + } +#endif + + // special IQueryInterface.queryInterface() + if (method_name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("queryInterface") )) + { + // oid + JLocalAutoRef jo_oid( + jni, jni->GetObjectField( + jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); + // type + JLocalAutoRef jo_type( + jni, jni->GetObjectArrayElement( jo_args, 0 ) ); + jni.ensure_no_exception(); + + JLocalAutoRef jo_type_name( + jni, jni->GetObjectField( + jo_type.get(), jni_info->m_field_Type__typeName ) ); + if (! jo_type_name.is()) + { + throw BridgeRuntimeError( + OUSTR("incomplete type object: no type name!") + + jni.get_stack_trace() ); + } + OUString type_name( + jstring_to_oustring( jni, (jstring) jo_type_name.get() ) ); + JNI_type_info const * info = + jni_info->get_type_info( jni, type_name ); + if (typelib_TypeClass_INTERFACE != info->m_td.get()->eTypeClass) + { + throw BridgeRuntimeError( + OUSTR("queryInterface() call demands an INTERFACE type!") ); + } + JNI_interface_type_info const * iface_info = + static_cast< JNI_interface_type_info const * >( info ); + + // getRegisteredInterface() already tested in JNI_proxy: + // perform queryInterface call on binary uno interface + uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >( + jni->GetLongField( + jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); + + uno_Any uno_ret; + void * uno_args[] = { &iface_info->m_td.get()->pWeakRef }; + uno_Any uno_exc_holder; + uno_Any * uno_exc = &uno_exc_holder; + // call binary uno + (*pUnoI->pDispatcher)( + pUnoI, jni_info->m_XInterface_queryInterface_td.get(), + &uno_ret, uno_args, &uno_exc ); + if (0 == uno_exc) + { + jobject jo_ret = 0; + if (typelib_TypeClass_INTERFACE == uno_ret.pType->eTypeClass) + { + uno_Interface * pUnoRet = + (uno_Interface *) uno_ret.pReserved; + if (0 != pUnoRet) + { + try + { + jo_ret = + bridge->map_to_java( jni, pUnoRet, iface_info ); + } + catch (...) + { + uno_any_destruct( &uno_ret, 0 ); + throw; + } + } + } + uno_any_destruct( &uno_ret, 0 ); + return jo_ret; + } + else + { + bridge->handle_uno_exc( jni, uno_exc ); + return 0; + } + } + + typelib_InterfaceTypeDescription * td = + reinterpret_cast< typelib_InterfaceTypeDescription * >( + jni->GetLongField( + jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) ); + uno_Interface * pUnoI = + reinterpret_cast< uno_Interface * >( + jni->GetLongField( + jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); + + typelib_TypeDescriptionReference ** ppAllMembers = td->ppAllMembers; + for ( sal_Int32 nPos = td->nAllMembers; nPos--; ) + { + // try to avoid getting typedescription as long as possible, + // because of a Mutex.acquire() in + // typelib_typedescriptionreference_getDescription() + typelib_TypeDescriptionReference * member_type = + ppAllMembers[ nPos ]; + + // check method_name against fully qualified type_name + // of member_type; type_name is of the form + // <name> "::" <method_name> *(":@" <idx> "," <idx> ":" <name>) + OUString const & type_name = + OUString::unacquired( &member_type->pTypeName ); + sal_Int32 offset = type_name.indexOf( ':' ) + 2; + OSL_ASSERT( + offset >= 2 && offset < type_name.getLength() + && type_name[offset - 1] == ':' ); + sal_Int32 remainder = type_name.getLength() - offset; + if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass) + { + if ((method_name.getLength() == remainder + || (method_name.getLength() < remainder + && type_name[offset + method_name.getLength()] == ':')) + && type_name.match(method_name, offset)) + { + TypeDescr member_td( member_type ); + typelib_InterfaceMethodTypeDescription * method_td = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member_td.get() ); + return bridge->call_uno( + jni, pUnoI, member_td.get(), + method_td->pReturnTypeRef, + method_td->nParams, method_td->pParams, + jo_args ); + } + } + else // attribute + { + OSL_ASSERT( + typelib_TypeClass_INTERFACE_ATTRIBUTE == + member_type->eTypeClass ); + + if (method_name.getLength() >= 3 + && (method_name.getLength() - 3 == remainder + || (method_name.getLength() - 3 < remainder + && type_name[ + offset + (method_name.getLength() - 3)] == ':')) + && method_name[1] == 'e' && method_name[2] == 't' + && rtl_ustr_compare_WithLength( + type_name.getStr() + offset, + method_name.getLength() - 3, + method_name.getStr() + 3, + method_name.getLength() - 3) == 0) + { + if ('g' == method_name[ 0 ]) + { + TypeDescr member_td( member_type ); + typelib_InterfaceAttributeTypeDescription * attr_td = + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member_td.get() ); + return bridge->call_uno( + jni, pUnoI, member_td.get(), + attr_td->pAttributeTypeRef, + 0, 0, + jo_args ); + } + else if ('s' == method_name[ 0 ]) + { + TypeDescr member_td( member_type ); + typelib_InterfaceAttributeTypeDescription * attr_td = + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member_td.get() ); + if (! attr_td->bReadOnly) + { + typelib_MethodParameter param; + param.pTypeRef = attr_td->pAttributeTypeRef; + param.bIn = sal_True; + param.bOut = sal_False; + return bridge->call_uno( + jni, pUnoI, member_td.get(), + jni_info->m_void_type.getTypeLibType(), + 1, ¶m, + jo_args ); + } + } + } + } + } + // the thing that should not be... no method info found! + OUStringBuffer buf( 64 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "calling undeclared function on interface ") ); + buf.append( OUString::unacquired( + &((typelib_TypeDescription *)td)->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); + buf.append( method_name ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + catch (BridgeRuntimeError & err) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("[jni_uno bridge error] " + "Java calling UNO method ") ); + buf.append( method_name ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); + buf.append( err.m_message ); + // notify RuntimeException + OString cstr_msg( + OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_JAVA_UTF8 ) ); + OSL_FAIL( cstr_msg.getStr() ); + if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr()) + != 0) + { + OSL_ASSERT( false ); + } + return 0; + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OString cstr_msg( + OString( RTL_CONSTASCII_STRINGPARAM( + "[jni_uno bridge error] " + "attaching current thread to java failed!") ) + + OUStringToOString( + jni.get_stack_trace(), RTL_TEXTENCODING_JAVA_UTF8 ) ); + OSL_FAIL( cstr_msg.getStr() ); + if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr()) + != 0) + { + OSL_ASSERT( false ); + } + return 0; + } +} + +//------------------------------------------------------------------------------ +JNIEXPORT void +JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J( + JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle ) + SAL_THROW_EXTERN_C() +{ + Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle ); + JNI_info const * jni_info = bridge->m_jni_info; + JNI_context jni( + jni_info, jni_env, + static_cast< jobject >( + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext )->getClassLoader() ) ); + + uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >( + jni->GetLongField( + jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); + typelib_TypeDescription * td = + reinterpret_cast< typelib_TypeDescription * >( + jni->GetLongField( + jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) ); + +#if OSL_DEBUG_LEVEL > 1 + { + JLocalAutoRef jo_oid( + jni, jni->GetObjectField( + jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); + OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); + OString cstr_msg( + OUStringToOString( + OUSTR("freeing java uno proxy: ") + oid, + RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg.getStr() ); + } +#endif + // revoke from uno env; has already been revoked from java env + (*bridge->m_uno_env->revokeInterface)( bridge->m_uno_env, pUnoI ); + // release receiver + (*pUnoI->release)( pUnoI ); + // release typedescription handle + typelib_typedescription_release( td ); + // release bridge handle + bridge->release(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/jni_uno2java.cxx b/bridges/source/jni_uno/jni_uno2java.cxx new file mode 100644 index 000000000000..5fa8fa3e01b3 --- /dev/null +++ b/bridges/source/jni_uno/jni_uno2java.cxx @@ -0,0 +1,875 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <sal/alloca.h> + +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "rtl/ustrbuf.hxx" + +#include "jni_bridge.h" + + +using namespace ::std; +using namespace ::rtl; + +namespace +{ +extern "C" +{ + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) + SAL_THROW_EXTERN_C(); + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) + SAL_THROW_EXTERN_C(); + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) + SAL_THROW_EXTERN_C(); + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_dispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * member_td, + void * uno_ret, void * uno_args[], uno_Any ** uno_exc ) + SAL_THROW_EXTERN_C(); +} +} + +namespace jni_uno +{ + +//______________________________________________________________________________ +void Bridge::handle_java_exc( + JNI_context const & jni, + JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const +{ + OSL_ASSERT( jo_exc.is() ); + if (! jo_exc.is()) + { + throw BridgeRuntimeError( + OUSTR("java exception occurred, but no java exception available!?") + + jni.get_stack_trace() ); + } + + JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) ); + JLocalAutoRef jo_class_name( + jni, jni->CallObjectMethodA( + jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) ); + jni.ensure_no_exception(); + OUString exc_name( + jstring_to_oustring( jni, (jstring) jo_class_name.get() ) ); + + ::com::sun::star::uno::TypeDescription td( exc_name.pData ); + if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass)) + { + // call toString() + JLocalAutoRef jo_descr( + jni, jni->CallObjectMethodA( + jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") ); + buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); + buf.append( jni.get_stack_trace( jo_exc.get() ) ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + + auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) ); + jvalue val; + val.l = jo_exc.get(); + map_to_uno( + jni, uno_data.get(), val, td.get()->pWeakRef, 0, + false /* no assign */, false /* no out param */ ); + +#if OSL_DEBUG_LEVEL > 0 + // patch Message, append stack trace + reinterpret_cast< ::com::sun::star::uno::Exception * >( + uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() ); +#endif + + typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); + uno_exc->pType = td.get()->pWeakRef; + uno_exc->pData = uno_data.release(); + +#if OSL_DEBUG_LEVEL > 1 + OUStringBuffer trace_buf( 128 ); + trace_buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("exception occurred uno->java: [") ); + trace_buf.append( exc_name ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + trace_buf.append( + reinterpret_cast< ::com::sun::star::uno::Exception const * >( + uno_exc->pData )->Message ); + OString cstr_trace( + OUStringToOString( + trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_trace.getStr() ); +#endif +} + +//______________________________________________________________________________ +void Bridge::call_java( + jobject javaI, typelib_InterfaceTypeDescription * iface_td, + sal_Int32 local_member_index, sal_Int32 function_pos_offset, + typelib_TypeDescriptionReference * return_type, + typelib_MethodParameter * params, sal_Int32 nParams, + void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const +{ + OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 ); + + JNI_guarded_context jni( + m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + m_java_env->pContext ) ); + + // assure fully initialized iface_td: + ::com::sun::star::uno::TypeDescription iface_holder; + if (! iface_td->aBase.bComplete) { + iface_holder = ::com::sun::star::uno::TypeDescription( + reinterpret_cast<typelib_TypeDescription *>(iface_td) ); + iface_holder.makeComplete(); + if (! iface_holder.get()->bComplete) { + OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") ); + buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) ); + buf.append( jni.get_stack_trace() ); + throw BridgeRuntimeError( buf.makeStringAndClear() ); + } + iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>( + iface_holder.get() ); + OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE ); + } + + // prepare java args, save param td +#ifdef BROKEN_ALLOCA + jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams ); +#else + jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams ); +#endif + + sal_Int32 nPos; + for ( nPos = 0; nPos < nParams; ++nPos ) + { + try + { + typelib_MethodParameter const & param = params[ nPos ]; + java_args[ nPos ].l = 0; // if out: build up array[ 1 ] + map_to_java( + jni, &java_args[ nPos ], + uno_args[ nPos ], + param.pTypeRef, 0, + sal_False != param.bIn /* convert uno value */, + sal_False != param.bOut /* build up array[ 1 ] */ ); + } + catch (...) + { + // cleanup + for ( sal_Int32 n = 0; n < nPos; ++n ) + { + typelib_MethodParameter const & param = params[ n ]; + if (param.bOut || + typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) + { + jni->DeleteLocalRef( java_args[ n ].l ); + } + } +#ifdef BROKEN_ALLOCA + free( java_args ); +#endif + throw; + } + } + + sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers; + OSL_ASSERT( base_members < iface_td->nAllMembers ); + sal_Int32 base_members_function_pos = + iface_td->pMapMemberIndexToFunctionIndex[ base_members ]; + sal_Int32 member_pos = base_members + local_member_index; + OSL_ENSURE( + member_pos < iface_td->nAllMembers, "### member pos out of range!" ); + sal_Int32 function_pos = + iface_td->pMapMemberIndexToFunctionIndex[ member_pos ] + + function_pos_offset; + OSL_ENSURE( + function_pos >= base_members_function_pos + && function_pos < iface_td->nMapFunctionIndexToMemberIndex, + "### illegal function index!" ); + function_pos -= base_members_function_pos; + + JNI_interface_type_info const * info = + static_cast< JNI_interface_type_info const * >( + m_jni_info->get_type_info( jni, &iface_td->aBase ) ); + jmethodID method_id = info->m_methods[ function_pos ]; + +#if OSL_DEBUG_LEVEL > 1 + OUStringBuffer trace_buf( 128 ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") ); + JLocalAutoRef jo_method( + jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) ); + jni.ensure_no_exception(); + JLocalAutoRef jo_descr( + jni, jni->CallObjectMethodA( + jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") ); + jo_descr.reset( + jni->CallObjectMethodA( + javaI, m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); + JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) ); + jo_descr.reset( + jni->CallObjectMethodA( + jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) ); + jni.ensure_no_exception(); + trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); + OString cstr_trace( + OUStringToOString( + trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_trace.getStr() ); +#endif + + // complex return value + JLocalAutoRef java_ret( jni ); + + switch (return_type->eTypeClass) + { + case typelib_TypeClass_VOID: + jni->CallVoidMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_CHAR: + *(sal_Unicode *)uno_ret = + jni->CallCharMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_BOOLEAN: + *(sal_Bool *)uno_ret = + jni->CallBooleanMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_BYTE: + *(sal_Int8 *)uno_ret = + jni->CallByteMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int16 *)uno_ret = + jni->CallShortMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_Int32 *)uno_ret = + jni->CallIntMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_Int64 *)uno_ret = + jni->CallLongMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_FLOAT: + *(float *)uno_ret = + jni->CallFloatMethodA( javaI, method_id, java_args ); + break; + case typelib_TypeClass_DOUBLE: + *(double *)uno_ret = + jni->CallDoubleMethodA( javaI, method_id, java_args ); + break; + default: + java_ret.reset( + jni->CallObjectMethodA( javaI, method_id, java_args ) ); + break; + } + + if (jni->ExceptionCheck()) + { + JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); + jni->ExceptionClear(); + + // release temp java local refs + for ( nPos = 0; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & param = params[ nPos ]; + if (param.bOut || + typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) + { + jni->DeleteLocalRef( java_args[ nPos ].l ); + } + } + + handle_java_exc( jni, jo_exc, *uno_exc ); + } + else // no exception + { + for ( nPos = 0; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & param = params[ nPos ]; + if (param.bOut) + { + try + { + map_to_uno( + jni, uno_args[ nPos ], + java_args[ nPos ], param.pTypeRef, 0, + sal_False != param.bIn /* assign if inout */, + true /* out param */ ); + } + catch (...) + { + // cleanup uno pure out + for ( sal_Int32 n = 0; n < nPos; ++n ) + { + typelib_MethodParameter const & p = params[ n ]; + if (! p.bIn) + { + uno_type_destructData( + uno_args[ n ], p.pTypeRef, 0 ); + } + } + // cleanup java temp local refs + for ( ; nPos < nParams; ++nPos ) + { + typelib_MethodParameter const & p = params[ nPos ]; + if (p.bOut || + typelib_TypeClass_DOUBLE < + p.pTypeRef->eTypeClass) + { + jni->DeleteLocalRef( java_args[ nPos ].l ); + } + } +#ifdef BROKEN_ALLOCA + free( java_args ); +#endif + throw; + } + jni->DeleteLocalRef( java_args[ nPos ].l ); + } + else // pure temp in param + { + if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) + jni->DeleteLocalRef( java_args[ nPos ].l ); + } + } + + // return value + if (typelib_TypeClass_DOUBLE < return_type->eTypeClass) + { + try + { + jvalue val; + val.l = java_ret.get(); + map_to_uno( + jni, uno_ret, val, return_type, 0, + false /* no assign */, false /* no out param */ ); + } + catch (...) + { + // cleanup uno pure out + for ( sal_Int32 i = 0; i < nParams; ++i ) + { + typelib_MethodParameter const & param = params[ i ]; + if (! param.bIn) + { + uno_type_destructData( + uno_args[ i ], param.pTypeRef, 0 ); + } + } +#ifdef BROKEN_ALLOCA + free( java_args ); +#endif + throw; + } + } // else: already set integral uno return value + + // no exception occurred + *uno_exc = 0; + } +#ifdef BROKEN_ALLOCA + free( java_args ); +#endif +} + +//==== a uno proxy wrapping a java interface =================================== +struct UNO_proxy : public uno_Interface +{ + mutable oslInterlockedCount m_ref; + Bridge const * m_bridge; + + // mapping information + jobject m_javaI; + jstring m_jo_oid; + OUString m_oid; + JNI_interface_type_info const * m_type_info; + + inline void acquire() const; + inline void release() const; + + // ctor + inline UNO_proxy( + JNI_context const & jni, Bridge const * bridge, + jobject javaI, jstring jo_oid, OUString const & oid, + JNI_interface_type_info const * info ); +}; + +//______________________________________________________________________________ +inline UNO_proxy::UNO_proxy( + JNI_context const & jni, Bridge const * bridge, + jobject javaI, jstring jo_oid, OUString const & oid, + JNI_interface_type_info const * info ) + : m_ref( 1 ), + m_oid( oid ), + m_type_info( info ) +{ + JNI_info const * jni_info = bridge->m_jni_info; + JLocalAutoRef jo_string_array( + jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) ); + jni.ensure_no_exception(); + jvalue args[ 3 ]; + args[ 0 ].l = javaI; + args[ 1 ].l = jo_string_array.get(); + args[ 2 ].l = info->m_type; + jobject jo_iface = jni->CallObjectMethodA( + jni_info->m_object_java_env, + jni_info->m_method_IEnvironment_registerInterface, args ); + jni.ensure_no_exception(); + + m_javaI = jni->NewGlobalRef( jo_iface ); + m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid ); + bridge->acquire(); + m_bridge = bridge; + + // uno_Interface + uno_Interface::acquire = UNO_proxy_acquire; + uno_Interface::release = UNO_proxy_release; + uno_Interface::pDispatcher = UNO_proxy_dispatch; +} + +//______________________________________________________________________________ +inline void UNO_proxy::acquire() const +{ + if (1 == osl_incrementInterlockedCount( &m_ref )) + { + // rebirth of proxy zombie + void * that = const_cast< UNO_proxy * >( this ); + // register at uno env + (*m_bridge->m_uno_env->registerProxyInterface)( + m_bridge->m_uno_env, &that, + UNO_proxy_free, m_oid.pData, + (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() ); +#if OSL_DEBUG_LEVEL > 1 + OSL_ASSERT( this == (void const * const)that ); +#endif + } +} + +//______________________________________________________________________________ +inline void UNO_proxy::release() const +{ + if (0 == osl_decrementInterlockedCount( &m_ref )) + { + // revoke from uno env on last release + (*m_bridge->m_uno_env->revokeInterface)( + m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) ); + } +} + + +//______________________________________________________________________________ +uno_Interface * Bridge::map_to_uno( + JNI_context const & jni, + jobject javaI, JNI_interface_type_info const * info ) const +{ + JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) ); + OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); + + uno_Interface * pUnoI = 0; + (*m_uno_env->getRegisteredInterface)( + m_uno_env, (void **)&pUnoI, + oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); + + if (0 == pUnoI) // no existing interface, register new proxy + { + // refcount initially 1 + pUnoI = new UNO_proxy( + jni, const_cast< Bridge * >( this ), + javaI, (jstring) jo_oid.get(), oid, info ); + + (*m_uno_env->registerProxyInterface)( + m_uno_env, (void **)&pUnoI, + UNO_proxy_free, + oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); + } + return pUnoI; +} + +} + +using namespace ::jni_uno; + +namespace +{ +extern "C" +{ + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) + SAL_THROW_EXTERN_C() +{ + UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy ); + Bridge const * bridge = that->m_bridge; + + if ( env != bridge->m_uno_env ) { + OSL_ASSERT(false); + } +#if OSL_DEBUG_LEVEL > 1 + OString cstr_msg( + OUStringToOString( + OUSTR("freeing binary uno proxy: ") + that->m_oid, + RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg.getStr() ); +#endif + + try + { + JNI_guarded_context jni( + bridge->m_jni_info, + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext ) ); + + jni->DeleteGlobalRef( that->m_javaI ); + jni->DeleteGlobalRef( that->m_jo_oid ); + } + catch (BridgeRuntimeError & err) + { +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg2( + OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr_msg2.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_FAIL( + "[jni_uno bridge error] attaching current thread to java failed!" ); + } + + bridge->release(); +#if OSL_DEBUG_LEVEL > 1 + *(int *)that = 0xdeadcafe; +#endif + delete that; +} + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) + SAL_THROW_EXTERN_C() +{ + UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); + that->acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) + SAL_THROW_EXTERN_C() +{ + UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); + that->release(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL UNO_proxy_dispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * member_td, + void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) + SAL_THROW_EXTERN_C() +{ + UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); + Bridge const * bridge = that->m_bridge; + +#if OSL_DEBUG_LEVEL > 1 + OUStringBuffer trace_buf( 64 ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") ); + trace_buf.append( OUString::unacquired( &member_td->pTypeName ) ); + trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") ); + trace_buf.append( that->m_oid ); + OString cstr_msg( + OUStringToOString( + trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg.getStr() ); +#endif + + try + { + switch (member_td->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_InterfaceAttributeTypeDescription const * attrib_td = + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + member_td ); + com::sun::star::uno::TypeDescription attrib_holder; + while ( attrib_td->pBaseRef != 0 ) { + attrib_holder = com::sun::star::uno::TypeDescription( + attrib_td->pBaseRef ); + OSL_ASSERT( + attrib_holder.get()->eTypeClass + == typelib_TypeClass_INTERFACE_ATTRIBUTE ); + attrib_td = reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + attrib_holder.get() ); + } + typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface; + + if (0 == uno_ret) // is setter method + { + typelib_MethodParameter param; + param.pTypeRef = attrib_td->pAttributeTypeRef; + param.bIn = sal_True; + param.bOut = sal_False; + + bridge->call_java( + that->m_javaI, iface_td, + attrib_td->nIndex, 1, // get, then set method + bridge->m_jni_info->m_void_type.getTypeLibType(), + ¶m, 1, + 0, uno_args, uno_exc ); + } + else // is getter method + { + bridge->call_java( + that->m_javaI, iface_td, attrib_td->nIndex, 0, + attrib_td->pAttributeTypeRef, + 0, 0, // no params + uno_ret, 0, uno_exc ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + typelib_InterfaceMethodTypeDescription const * method_td = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + member_td ); + com::sun::star::uno::TypeDescription method_holder; + while ( method_td->pBaseRef != 0 ) { + method_holder = com::sun::star::uno::TypeDescription( + method_td->pBaseRef ); + OSL_ASSERT( + method_holder.get()->eTypeClass + == typelib_TypeClass_INTERFACE_METHOD ); + method_td = reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + method_holder.get() ); + } + typelib_InterfaceTypeDescription * iface_td = method_td->pInterface; + + switch ( method_td->aBase.nPosition ) + { + case 0: // queryInterface() + { + TypeDescr demanded_td( + *reinterpret_cast< typelib_TypeDescriptionReference ** >( + uno_args[ 0 ] ) ); + if (typelib_TypeClass_INTERFACE != + demanded_td.get()->eTypeClass) + { + throw BridgeRuntimeError( + OUSTR("queryInterface() call demands " + "an INTERFACE type!") ); + } + + uno_Interface * pInterface = 0; + (*bridge->m_uno_env->getRegisteredInterface)( + bridge->m_uno_env, + (void **) &pInterface, that->m_oid.pData, + (typelib_InterfaceTypeDescription *)demanded_td.get() ); + + if (0 == pInterface) + { + JNI_info const * jni_info = bridge->m_jni_info; + JNI_guarded_context jni( + jni_info, + reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( + bridge->m_java_env->pContext ) ); + + JNI_interface_type_info const * info = + static_cast< JNI_interface_type_info const * >( + jni_info->get_type_info( jni, demanded_td.get() ) ); + + jvalue args[ 2 ]; + args[ 0 ].l = info->m_type; + args[ 1 ].l = that->m_javaI; + + JLocalAutoRef jo_ret( + jni, jni->CallStaticObjectMethodA( + jni_info->m_class_UnoRuntime, + jni_info->m_method_UnoRuntime_queryInterface, + args ) ); + + if (jni->ExceptionCheck()) + { + JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); + jni->ExceptionClear(); + bridge->handle_java_exc( jni, jo_exc, *uno_exc ); + } + else + { + if (jo_ret.is()) + { +#if OSL_DEBUG_LEVEL > 0 + JLocalAutoRef jo_oid( + jni, compute_oid( jni, jo_ret.get() ) ); + OUString oid( jstring_to_oustring( + jni, (jstring) jo_oid.get() ) ); + OSL_ENSURE( + oid.equals( that->m_oid ), + "### different oids!" ); +#endif + // refcount initially 1 + uno_Interface * pUnoI2 = new UNO_proxy( + jni, bridge, jo_ret.get(), + that->m_jo_oid, that->m_oid, info ); + + (*bridge->m_uno_env->registerProxyInterface)( + bridge->m_uno_env, + (void **) &pUnoI2, + UNO_proxy_free, that->m_oid.pData, + reinterpret_cast< + typelib_InterfaceTypeDescription * >( + info->m_td.get() ) ); + + uno_any_construct( + (uno_Any *)uno_ret, &pUnoI2, + demanded_td.get(), 0 ); + (*pUnoI2->release)( pUnoI2 ); + } + else // object does not support demanded interface + { + uno_any_construct( + reinterpret_cast< uno_Any * >( uno_ret ), + 0, 0, 0 ); + } + // no exception occurred + *uno_exc = 0; + } + } + else + { + uno_any_construct( + reinterpret_cast< uno_Any * >( uno_ret ), + &pInterface, demanded_td.get(), 0 ); + (*pInterface->release)( pInterface ); + *uno_exc = 0; + } + break; + } + case 1: // acquire this proxy + that->acquire(); + *uno_exc = 0; + break; + case 2: // release this proxy + that->release(); + *uno_exc = 0; + break; + default: // arbitrary method call + bridge->call_java( + that->m_javaI, iface_td, method_td->nIndex, 0, + method_td->pReturnTypeRef, + method_td->pParams, method_td->nParams, + uno_ret, uno_args, uno_exc ); + break; + } + break; + } + default: + { + throw BridgeRuntimeError( + OUSTR("illegal member type description!") ); + } + } + } + catch (BridgeRuntimeError & err) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "[jni_uno bridge error] UNO calling Java method ") ); + if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass || + typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass) + { + buf.append( OUString::unacquired( + &reinterpret_cast< + typelib_InterfaceMemberTypeDescription const * >( + member_td )->pMemberName ) ); + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); + buf.append( err.m_message ); + // binary identical struct + ::com::sun::star::uno::RuntimeException exc( + buf.makeStringAndClear(), + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface >() ); + ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); + uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg2( + OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "%s", cstr_msg2.getStr() ); +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + // binary identical struct + ::com::sun::star::uno::RuntimeException exc( + OUSTR("[jni_uno bridge error] attaching current thread " + "to java failed!"), + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface >() ); + ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); + uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); +#if OSL_DEBUG_LEVEL > 0 + OString cstr_msg2( + OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_FAIL( cstr_msg2.getStr() ); +#endif + } +} + +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/jni_uno/makefile.mk b/bridges/source/jni_uno/makefile.mk new file mode 100644 index 000000000000..1474a86cd741 --- /dev/null +++ b/bridges/source/jni_uno/makefile.mk @@ -0,0 +1,86 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=bridges +TARGET=java_uno +USE_DEFFILE=TRUE +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(SOLAR_JAVA)"=="" +nojava: + @echo "Not building jni-uno bridge because Java is disabled" +.ENDIF + +# --- Files -------------------------------------------------------- + +.IF "$(GUI)$(COM)" == "WNTGCC" +.IF "$(EXCEPTIONS)" == "sjlj" +CFLAGS += -DBROKEN_ALLOCA +.ENDIF +.ENDIF + +SLOFILES= \ + $(SLO)$/jni_info.obj \ + $(SLO)$/jni_data.obj \ + $(SLO)$/jni_uno2java.obj \ + $(SLO)$/jni_java2uno.obj \ + $(SLO)$/jni_bridge.obj \ + $(SLO)$/nativethreadpool.obj + +SHL1TARGET=$(TARGET) + +SHL1STDLIBS= \ + $(JVMACCESSLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) + +SHL1VERSIONMAP=$(TARGET).map + +SHL1CREATEJNILIB=TRUE +SHL1IMPLIB=i$(TARGET) +SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) +SHL1RPATH=URELIB + +.IF "$(debug)" != "" +.IF "$(COM)" == "MSC" +CFLAGS += -Ob0 +.ENDIF +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/jni_uno/nativethreadpool.cxx b/bridges/source/jni_uno/nativethreadpool.cxx new file mode 100644 index 000000000000..9c92e89c5b07 --- /dev/null +++ b/bridges/source/jni_uno/nativethreadpool.cxx @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "jvmaccess/virtualmachine.hxx" +#include "rtl/byteseq.h" +#include "rtl/byteseq.hxx" +#include "rtl/memory.h" +#include "rtl/ref.hxx" +#include "sal/types.h" +#include "uno/threadpool.h" + +#include "jni.h" + +#include <new> + +/* The native implementation part of + * jurt/com/sun/star/lib/uno/environments/remote/NativeThreadPool.java. + */ + +namespace { + +struct Pool { + Pool(rtl::Reference< jvmaccess::VirtualMachine > const & theVirtualMachine, + jmethodID theExecute, uno_ThreadPool thePool): + virtualMachine(theVirtualMachine), execute(theExecute), pool(thePool) {} + + rtl::Reference< jvmaccess::VirtualMachine > virtualMachine; + jmethodID execute; + uno_ThreadPool pool; +}; + +struct Job { + Job(Pool * thePool, jobject theJob): pool(thePool), job(theJob) {} + + Pool * pool; + jobject job; +}; + +void throwOutOfMemory(JNIEnv * env) { + jclass c = env->FindClass("java/lang/OutOfMemoryError"); + if (c != 0) { + env->ThrowNew(c, ""); + } +} + +} + +extern "C" { + +static void SAL_CALL executeRequest(void * data) { + Job * job = static_cast< Job * >(data); + try { + jvmaccess::VirtualMachine::AttachGuard guard(job->pool->virtualMachine); + JNIEnv * env = guard.getEnvironment(); + // Failure of the following Job.execute Java call is ignored; if that + // call fails, it should be due to a java.lang.Error, which is not + // handled well, anyway: + env->CallObjectMethod(job->job, job->pool->execute); + env->DeleteGlobalRef(job->job); + delete job; + } catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) { + //TODO: DeleteGlobalRef(job->job) + delete job; + } +} + +} + +extern "C" JNIEXPORT jbyteArray JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_threadId( + JNIEnv * env, jclass) SAL_THROW_EXTERN_C() +{ + sal_Sequence * s = 0; + uno_getIdOfCurrentThread(&s); //TODO: out of memory + uno_releaseIdFromCurrentThread(); + rtl::ByteSequence seq(s); + rtl_byte_sequence_release(s); + sal_Int32 n = seq.getLength(); + jbyteArray a = env->NewByteArray(n); + // sal_Int32 and jsize are compatible here + if (a == 0) { + return 0; + } + void * p = env->GetPrimitiveArrayCritical(a, 0); + if (p == 0) { + return 0; + } + rtl_copyMemory(p, seq.getConstArray(), n); + // sal_Int8 and jbyte ought to be compatible + env->ReleasePrimitiveArrayCritical(a, p, 0); + return a; +} + +extern "C" JNIEXPORT jlong JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_create( + JNIEnv * env, jclass) SAL_THROW_EXTERN_C() +{ + JavaVM * vm; + if (env->GetJavaVM(&vm) != JNI_OK) { //TODO: no Java exception raised? + jclass c = env->FindClass("java/lang/RuntimeException"); + if (c != 0) { + env->ThrowNew(c, "JNI GetJavaVM failed"); + } + return 0; + } + jclass c = env->FindClass("com/sun/star/lib/uno/environments/remote/Job"); + if (c == 0) { + return 0; + } + jmethodID execute = env->GetMethodID(c, "execute", "()Ljava/lang/Object;"); + if (execute == 0) { + return 0; + } + try { + return reinterpret_cast< jlong >(new Pool( + new jvmaccess::VirtualMachine(vm, env->GetVersion(), false, env), + execute, uno_threadpool_create())); + } catch (std::bad_alloc) { + throwOutOfMemory(env); + return 0; + } +} + +extern "C" JNIEXPORT void JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_attach( + JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() +{ + uno_threadpool_attach(reinterpret_cast< Pool * >(pool)->pool); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_enter( + JNIEnv * env, jclass, jlong pool) SAL_THROW_EXTERN_C() +{ + jobject job; + uno_threadpool_enter( + reinterpret_cast< Pool * >(pool)->pool, + reinterpret_cast< void ** >(&job)); + if (job == 0) { + return 0; + } + jobject ref = env->NewLocalRef(job); + env->DeleteGlobalRef(job); + return ref; +} + +extern "C" JNIEXPORT void JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_detach( + JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() +{ + uno_threadpool_detach(reinterpret_cast< Pool * >(pool)->pool); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_putJob( + JNIEnv * env, jclass, jlong pool, jbyteArray threadId, jobject job, + jboolean request, jboolean oneWay) SAL_THROW_EXTERN_C() +{ + void * s = env->GetPrimitiveArrayCritical(threadId, 0); + if (s == 0) { + return; + } + rtl::ByteSequence seq( + static_cast< sal_Int8 * >(s), env->GetArrayLength(threadId)); + // sal_Int8 and jbyte ought to be compatible; sal_Int32 and jsize are + // compatible here + //TODO: out of memory + env->ReleasePrimitiveArrayCritical(threadId, s, JNI_ABORT); + Pool * p = reinterpret_cast< Pool * >(pool); + jobject ref = env->NewGlobalRef(job); + if (ref == 0) { + return; + } + Job * j = 0; + if (request) { + j = new(std::nothrow) Job(p, ref); + if (j == 0) { + env->DeleteGlobalRef(ref); + throwOutOfMemory(env); + return; + } + } + uno_threadpool_putJob( + p->pool, seq.getHandle(), + request ? static_cast< void * >(j) : static_cast< void * >(ref), + request ? executeRequest : 0, oneWay); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_dispose( + JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() +{ + uno_threadpool_dispose(reinterpret_cast< Pool * >(pool)->pool); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_destroy( + JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() +{ + Pool * p = reinterpret_cast< Pool * >(pool); + uno_threadpool_destroy(p->pool); + delete p; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/com/sun/star/lib/TestBed.java b/bridges/test/com/sun/star/lib/TestBed.java new file mode 100644 index 000000000000..2e96a724ebc3 --- /dev/null +++ b/bridges/test/com/sun/star/lib/TestBed.java @@ -0,0 +1,232 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib; + +import com.sun.star.bridge.XBridge; +import com.sun.star.bridge.XBridgeFactory; +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.comp.helper.Bootstrap; +import com.sun.star.connection.Acceptor; +import com.sun.star.connection.Connector; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.connection.XConnector; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; + +public final class TestBed { + public boolean execute(XInstanceProvider provider, boolean waitForServer, + Class client, long wait) throws Exception { + // assert client.isAssignableFrom(client) && wait >= 0; + synchronized (lock) { + server = new Server(provider); + server.start(); + server.waitAccepting(); + } + Process p = Runtime.getRuntime().exec(new String[] { + "java", "-classpath", System.getProperty("java.class.path"), +/* + "-Xdebug", + "-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n", +*/ + client.getName() }); + pipe(p.getInputStream(), System.out, "CO> "); + pipe(p.getErrorStream(), System.err, "CE> "); + boolean clientDone = false; + if (wait <= 0) { + clientDone = p.waitFor() == CLIENT_DONE; + } else { + try { + Thread.sleep(wait); + } catch (InterruptedException e) { + p.destroy(); + throw e; + } + try { + clientDone = p.exitValue() == CLIENT_DONE; + } catch (IllegalThreadStateException e) { + p.destroy(); + } + } + boolean success = clientDone; + if (waitForServer) { + success &= server.waitDone(); + } + return success; + } + + public void serverDone(boolean success) { + synchronized (lock) { + server.done(success); + } + } + + private void pipe(final InputStream in, final PrintStream out, + final String prefix) { + new Thread("Pipe: " + prefix) { + public void run() { + BufferedReader r + = new BufferedReader(new InputStreamReader(in)); + try { + for (;;) { + String s = r.readLine(); + if (s == null) { + break; + } + out.println(prefix + s); + } + } catch (java.io.IOException e) { + e.printStackTrace(System.err); + } + } + }.start(); + } + + public static abstract class Client { + protected abstract boolean run(XComponentContext context) + throws Throwable; + + protected final String getConnectionDescription() { + return connectionDescription; + } + + protected final String getProtocolDescription() { + return protocolDescription; + } + + protected final XBridge getBridge(XComponentContext context) + throws com.sun.star.uno.Exception + { + XConnector connector = Connector.create(context); + XBridgeFactory factory = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + System.out.println("Client: Connecting..."); + XConnection connection = connector.connect(connectionDescription); + System.out.println("Client: ...connected..."); + XBridge bridge = factory.createBridge( + "", protocolDescription, connection, null); + System.out.println("Client: ...bridged."); + return bridge; + } + + protected final void execute() { + int status = CLIENT_FAILED; + try { + if (run(Bootstrap.createInitialComponentContext(null))) { + status = CLIENT_DONE; + } + } catch (Throwable e) { + e.printStackTrace(System.err); + } + System.exit(status); + } + } + + private static final class Server extends Thread { + public Server(XInstanceProvider provider) { + super("Server"); + // assert provider != null; + this.provider = provider; + } + + public void run() { + try { + XComponentContext context + = Bootstrap.createInitialComponentContext(null); + XAcceptor acceptor = Acceptor.create(context); + XBridgeFactory factory + = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + System.out.println("Server: Accepting..."); + synchronized (this) { + state = ACCEPTING; + notifyAll(); + } + for (;;) { + XConnection connection = acceptor.accept( + connectionDescription); + System.out.println("Server: ...connected..."); + XBridge bridge = factory.createBridge( + "", protocolDescription, connection, provider); + System.out.println("Server: ...bridged."); + } + } catch (Throwable e) { + e.printStackTrace(System.err); + } + } + + public synchronized void waitAccepting() throws InterruptedException { + while (state < ACCEPTING) { + wait(); + } + } + + public synchronized boolean waitDone() throws InterruptedException { + while (state <= ACCEPTING) { + wait(); + } + return state == SUCCEEDED; + } + + public synchronized void done(boolean success) { + state = success ? SUCCEEDED : FAILED; + notifyAll(); + } + + private static final int INITIAL = 0; + private static final int ACCEPTING = 1; + private static final int FAILED = 2; + private static final int SUCCEEDED = 3; + + private final XInstanceProvider provider; + + private int state = INITIAL; + } + + private static final int TEST_SUCCEEDED = 0; + private static final int TEST_FAILED = 1; + private static final int TEST_ERROR = 2; + + private static final int CLIENT_FAILED = 0; + private static final int CLIENT_DONE = 123; + + private static final String connectionDescription + = "socket,host=localhost,port=12345"; + private static final String protocolDescription = "urp"; + + private final Object lock = new Object(); + private Server server = null; +} diff --git a/bridges/test/com/sun/star/lib/makefile.mk b/bridges/test/com/sun/star/lib/makefile.mk new file mode 100644 index 000000000000..3af025ba8667 --- /dev/null +++ b/bridges/test/com/sun/star/lib/makefile.mk @@ -0,0 +1,36 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ := ..$/..$/..$/..$/.. +PRJNAME := bridges +TARGET := test_com_sun_star_lib + +PACKAGE := com$/sun$/star$/lib +JAVAFILES := TestBed.java +JARFILES := juh.jar jurt.jar ridl.jar + +.INCLUDE: javaunittest.mk diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug107753_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug107753_Test.java new file mode 100644 index 000000000000..badc38df256e --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug107753_Test.java @@ -0,0 +1,394 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #107753#. + * + * <p>Bug #107753# "Java UNO: Proxies should implement intuitive semantics of + * equals and hashCode" requests that two proxies are equal iff they represent + * the same UNO object. This implies that if two proxies repsent the same UNO + * object, they must have the same hash code.</p> + */ +public final class Bug107753_Test extends ComplexTestCase { + public String getTestObjectName() { + return getClass().getName(); + } + + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + TestBed t = new TestBed(); + assure("test", t.execute(new Provider(t), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + boolean success = true; + XTransport transport = UnoRuntime.queryInterface( + XTransport.class, getBridge(context).getInstance("Transport")); + + Object obj1a = new XType1() {}; + XType1 obj1b = UnoRuntime.queryInterface(XType1.class, obj1a); + success &= test("obj1a == obj1b", obj1a == obj1b); + + Object obj2a = new XType2() {}; + XType2 obj2b = UnoRuntime.queryInterface(XType2.class, obj2a); + success &= test("obj2a == obj2b", obj2a == obj2b); + + Object obj3a = transport.getType1(); + XType1 obj3b = UnoRuntime.queryInterface(XType1.class, obj3a); + success &= test( + "obj3a != obj3b; only meaningful as long as different proxy" + + " instances are used for different UNO interfaces of one UNO" + + " object", + obj3a != obj3b); + + Object obj4a = transport.getType2(); + XType2 obj4b = UnoRuntime.queryInterface(XType2.class, obj4a); + success &= test( + "obj4a != obj4b; only meaningful as long as different proxy" + + " instances are used for different UNO interfaces of one UNO" + + " object", + obj4a != obj4b); + + success &= test("UnoRuntime.areSame(null, null)", + UnoRuntime.areSame(null, null)); + success &= test("!UnoRuntime.areSame(null, obj1a)", + !UnoRuntime.areSame(null, obj1a)); + success &= test("!UnoRuntime.areSame(null, obj1b)", + !UnoRuntime.areSame(null, obj1b)); + success &= test("!UnoRuntime.areSame(null, obj2a)", + !UnoRuntime.areSame(null, obj2a)); + success &= test("!UnoRuntime.areSame(null, obj2b)", + !UnoRuntime.areSame(null, obj2b)); + success &= test("!UnoRuntime.areSame(null, obj3a)", + !UnoRuntime.areSame(null, obj3a)); + success &= test("!UnoRuntime.areSame(null, obj3b)", + !UnoRuntime.areSame(null, obj3b)); + success &= test("!UnoRuntime.areSame(null, obj4a)", + !UnoRuntime.areSame(null, obj4a)); + success &= test("!UnoRuntime.areSame(null, obj4b)", + !UnoRuntime.areSame(null, obj4b)); + + success &= test("!obj1a.equals(null)", !obj1a.equals(null)); + success &= test("!UnoRuntime.areSame(obj1a, null)", + !UnoRuntime.areSame(obj1a, null)); + success &= test("obj1a.equals(obj1a)", obj1a.equals(obj1a)); + success &= test("UnoRuntime.areSame(obj1a, obj1a)", + UnoRuntime.areSame(obj1a, obj1a)); + success &= test("obj1a.equals(obj1b)", obj1a.equals(obj1b)); + success &= test("UnoRuntime.areSame(obj1a, obj1b)", + UnoRuntime.areSame(obj1a, obj1b)); + success &= test("!obj1a.equals(obj2a)", !obj1a.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj1a, obj2a)", + !UnoRuntime.areSame(obj1a, obj2a)); + success &= test("!obj1a.equals(obj2b)", !obj1a.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj1a, obj2b)", + !UnoRuntime.areSame(obj1a, obj2b)); + success &= test("!obj1a.equals(obj3a)", !obj1a.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj1a, obj3a)", + !UnoRuntime.areSame(obj1a, obj3a)); + success &= test("!obj1a.equals(obj3b)", !obj1a.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj1a, obj3b)", + !UnoRuntime.areSame(obj1a, obj3b)); + success &= test("!obj1a.equals(obj4a)", !obj1a.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj1a, obj4a)", + !UnoRuntime.areSame(obj1a, obj4a)); + success &= test("!obj1a.equals(obj4b)", !obj1a.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj1a, obj4b)", + !UnoRuntime.areSame(obj1a, obj4b)); + + success &= test("!obj1b.equals(null)", !obj1b.equals(null)); + success &= test("!UnoRuntime.areSame(obj1b, null)", + !UnoRuntime.areSame(obj1b, null)); + success &= test("obj1b.equals(obj1a)", obj1b.equals(obj1a)); + success &= test("UnoRuntime.areSame(obj1b, obj1a)", + UnoRuntime.areSame(obj1b, obj1a)); + success &= test("obj1b.equals(obj1b)", obj1b.equals(obj1b)); + success &= test("UnoRuntime.areSame(obj1b, obj1b)", + UnoRuntime.areSame(obj1b, obj1b)); + success &= test("!obj1b.equals(obj2a)", !obj1b.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj1b, obj2a)", + !UnoRuntime.areSame(obj1b, obj2a)); + success &= test("!obj1b.equals(obj2b)", !obj1b.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj1b, obj2b)", + !UnoRuntime.areSame(obj1b, obj2b)); + success &= test("!obj1b.equals(obj3a)", !obj1b.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj1b, obj3a)", + !UnoRuntime.areSame(obj1b, obj3a)); + success &= test("!obj1b.equals(obj3b)", !obj1b.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj1b, obj3b)", + !UnoRuntime.areSame(obj1b, obj3b)); + success &= test("!obj1b.equals(obj4a)", !obj1b.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj1b, obj4a)", + !UnoRuntime.areSame(obj1b, obj4a)); + success &= test("!obj1b.equals(obj4b)", !obj1b.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj1b, obj4b)", + !UnoRuntime.areSame(obj1b, obj4b)); + + success &= test("!obj2a.equals(null)", !obj2a.equals(null)); + success &= test("!UnoRuntime.areSame(obj2a, null)", + !UnoRuntime.areSame(obj2a, null)); + success &= test("!obj2a.equals(obj1a)", !obj2a.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj2a, obj1a)", + !UnoRuntime.areSame(obj2a, obj1a)); + success &= test("!obj2a.equals(obj1b)", !obj2a.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj2a, obj1b)", + !UnoRuntime.areSame(obj2a, obj1b)); + success &= test("obj2a.equals(obj2a)", obj2a.equals(obj2a)); + success &= test("UnoRuntime.areSame(obj2a, obj2a)", + UnoRuntime.areSame(obj2a, obj2a)); + success &= test("obj2a.equals(obj2b)", obj2a.equals(obj2b)); + success &= test("UnoRuntime.areSame(obj2a, obj2b)", + UnoRuntime.areSame(obj2a, obj2b)); + success &= test("!obj2a.equals(obj3a)", !obj2a.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj2a, obj3a)", + !UnoRuntime.areSame(obj2a, obj3a)); + success &= test("!obj2a.equals(obj3b)", !obj2a.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj2a, obj3b)", + !UnoRuntime.areSame(obj2a, obj3b)); + success &= test("!obj2a.equals(obj4a)", !obj2a.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj2a, obj4a)", + !UnoRuntime.areSame(obj2a, obj4a)); + success &= test("!obj2a.equals(obj4b)", !obj2a.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj2a, obj4b)", + !UnoRuntime.areSame(obj2a, obj4b)); + + success &= test("!obj2b.equals(null)", !obj2b.equals(null)); + success &= test("!UnoRuntime.areSame(obj2b, null)", + !UnoRuntime.areSame(obj2b, null)); + success &= test("!obj2b.equals(obj1a)", !obj2b.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj2b, obj1a)", + !UnoRuntime.areSame(obj2b, obj1a)); + success &= test("!obj2b.equals(obj1b)", !obj2b.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj2b, obj1b)", + !UnoRuntime.areSame(obj2b, obj1b)); + success &= test("obj2b.equals(obj2a)", obj2b.equals(obj2a)); + success &= test("UnoRuntime.areSame(obj2b, obj2a)", + UnoRuntime.areSame(obj2b, obj2a)); + success &= test("obj2b.equals(obj2b)", obj2b.equals(obj2b)); + success &= test("UnoRuntime.areSame(obj2b, obj2b)", + UnoRuntime.areSame(obj2b, obj2b)); + success &= test("!obj2b.equals(obj3a)", !obj2b.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj2b, obj3a)", + !UnoRuntime.areSame(obj2b, obj3a)); + success &= test("!obj2b.equals(obj3b)", !obj2b.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj2b, obj3b)", + !UnoRuntime.areSame(obj2b, obj3b)); + success &= test("!obj2b.equals(obj4a)", !obj2b.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj2b, obj4a)", + !UnoRuntime.areSame(obj2b, obj4a)); + success &= test("!obj2b.equals(obj4b)", !obj2b.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj2b, obj4b)", + !UnoRuntime.areSame(obj2b, obj4b)); + + success &= test("!obj3a.equals(null)", !obj3a.equals(null)); + success &= test("!UnoRuntime.areSame(obj3a, null)", + !UnoRuntime.areSame(obj3a, null)); + success &= test("!obj3a.equals(obj1a)", !obj3a.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj3a, obj1a)", + !UnoRuntime.areSame(obj3a, obj1a)); + success &= test("!obj3a.equals(obj1b)", !obj3a.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj3a, obj1b)", + !UnoRuntime.areSame(obj3a, obj1b)); + success &= test("!obj3a.equals(obj2a)", !obj3a.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj3a, obj2a)", + !UnoRuntime.areSame(obj3a, obj2a)); + success &= test("!obj3a.equals(obj2b)", !obj3a.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj3a, obj2b)", + !UnoRuntime.areSame(obj3a, obj2b)); + success &= test("obj3a.equals(obj3a)", obj3a.equals(obj3a)); + success &= test("UnoRuntime.areSame(obj3a, obj3a)", + UnoRuntime.areSame(obj3a, obj3a)); + success &= test("obj3a.equals(obj3b)", obj3a.equals(obj3b)); + success &= test("UnoRuntime.areSame(obj3a, obj3b)", + UnoRuntime.areSame(obj3a, obj3b)); + success &= test("!obj3a.equals(obj4a)", !obj3a.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj3a, obj4a)", + !UnoRuntime.areSame(obj3a, obj4a)); + success &= test("!obj3a.equals(obj4b)", !obj3a.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj3a, obj4b)", + !UnoRuntime.areSame(obj3a, obj4b)); + + success &= test("!obj3b.equals(null)", !obj3b.equals(null)); + success &= test("!UnoRuntime.areSame(obj3b, null)", + !UnoRuntime.areSame(obj3b, null)); + success &= test("!obj3b.equals(obj1a)", !obj3b.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj3b, obj1a)", + !UnoRuntime.areSame(obj3b, obj1a)); + success &= test("!obj3b.equals(obj1b)", !obj3b.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj3b, obj1b)", + !UnoRuntime.areSame(obj3b, obj1b)); + success &= test("!obj3b.equals(obj2a)", !obj3b.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj3b, obj2a)", + !UnoRuntime.areSame(obj3b, obj2a)); + success &= test("!obj3b.equals(obj2b)", !obj3b.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj3b, obj2b)", + !UnoRuntime.areSame(obj3b, obj2b)); + success &= test("obj3b.equals(obj3a)", obj3b.equals(obj3a)); + success &= test("UnoRuntime.areSame(obj3b, obj3a)", + UnoRuntime.areSame(obj3b, obj3a)); + success &= test("obj3b.equals(obj3b)", obj3b.equals(obj3b)); + success &= test("UnoRuntime.areSame(obj3b, obj3b)", + UnoRuntime.areSame(obj3b, obj3b)); + success &= test("!obj3b.equals(obj4a)", !obj3b.equals(obj4a)); + success &= test("!UnoRuntime.areSame(obj3b, obj4a)", + !UnoRuntime.areSame(obj3b, obj4a)); + success &= test("!obj3b.equals(obj4b)", !obj3b.equals(obj4b)); + success &= test("!UnoRuntime.areSame(obj3b, obj4b)", + !UnoRuntime.areSame(obj3b, obj4b)); + + success &= test("!obj4a.equals(null)", !obj4a.equals(null)); + success &= test("!UnoRuntime.areSame(obj4a, null)", + !UnoRuntime.areSame(obj4a, null)); + success &= test("!obj4a.equals(obj1a)", !obj4a.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj4a, obj1a)", + !UnoRuntime.areSame(obj4a, obj1a)); + success &= test("!obj4a.equals(obj1b)", !obj4a.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj4a, obj1b)", + !UnoRuntime.areSame(obj4a, obj1b)); + success &= test("!obj4a.equals(obj2a)", !obj4a.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj4a, obj2a)", + !UnoRuntime.areSame(obj4a, obj2a)); + success &= test("!obj4a.equals(obj2b)", !obj4a.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj4a, obj2b)", + !UnoRuntime.areSame(obj4a, obj2b)); + success &= test("!obj4a.equals(obj3a)", !obj4a.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj4a, obj3a)", + !UnoRuntime.areSame(obj4a, obj3a)); + success &= test("!obj4a.equals(obj3b)", !obj4a.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj4a, obj3b)", + !UnoRuntime.areSame(obj4a, obj3b)); + success &= test("obj4a.equals(obj4a)", obj4a.equals(obj4a)); + success &= test("UnoRuntime.areSame(obj4a, obj4a)", + UnoRuntime.areSame(obj4a, obj4a)); + success &= test("obj4a.equals(obj4b)", obj4a.equals(obj4b)); + success &= test("UnoRuntime.areSame(obj4a, obj4b)", + UnoRuntime.areSame(obj4a, obj4b)); + + success &= test("!obj4b.equals(null)", !obj4b.equals(null)); + success &= test("!UnoRuntime.areSame(obj4b, null)", + !UnoRuntime.areSame(obj4b, null)); + success &= test("!obj4b.equals(obj1a)", !obj4b.equals(obj1a)); + success &= test("!UnoRuntime.areSame(obj4b, obj1a)", + !UnoRuntime.areSame(obj4b, obj1a)); + success &= test("!obj4b.equals(obj1b)", !obj4b.equals(obj1b)); + success &= test("!UnoRuntime.areSame(obj4b, obj1b)", + !UnoRuntime.areSame(obj4b, obj1b)); + success &= test("!obj4b.equals(obj2a)", !obj4b.equals(obj2a)); + success &= test("!UnoRuntime.areSame(obj4b, obj2a)", + !UnoRuntime.areSame(obj4b, obj2a)); + success &= test("!obj4b.equals(obj2b)", !obj4b.equals(obj2b)); + success &= test("!UnoRuntime.areSame(obj4b, obj2b)", + !UnoRuntime.areSame(obj4b, obj2b)); + success &= test("!obj4b.equals(obj3a)", !obj4b.equals(obj3a)); + success &= test("!UnoRuntime.areSame(obj4b, obj3a)", + !UnoRuntime.areSame(obj4b, obj3a)); + success &= test("!obj4b.equals(obj3b)", !obj4b.equals(obj3b)); + success &= test("!UnoRuntime.areSame(obj4b, obj3b)", + !UnoRuntime.areSame(obj4b, obj3b)); + success &= test("obj4b.equals(obj4a)", obj4b.equals(obj4a)); + success &= test("UnoRuntime.areSame(obj4b, obj4a)", + UnoRuntime.areSame(obj4b, obj4a)); + success &= test("obj4b.equals(obj4b)", obj4b.equals(obj4b)); + success &= test("UnoRuntime.areSame(obj4b, obj4b)", + UnoRuntime.areSame(obj4b, obj4b)); + + success &= test("obj1a.hashCode() == obj1b.hashCode()", + obj1a.hashCode() == obj1b.hashCode()); + success &= test("obj2a.hashCode() == obj2b.hashCode()", + obj2a.hashCode() == obj2b.hashCode()); + success &= test("obj3a.hashCode() == obj3b.hashCode()", + obj3a.hashCode() == obj3b.hashCode()); + success &= test("obj4a.hashCode() == obj4b.hashCode()", + obj4a.hashCode() == obj4b.hashCode()); + + return success; + } + + private static boolean test(String message, boolean condition) { + if (!condition) { + System.err.println("Failed: " + message); + } + return condition; + } + } + + private static final class Provider implements XInstanceProvider { + public Provider(TestBed testBed) { + this.testBed = testBed; + } + + public Object getInstance(String instanceName) { + return new XTransport() { + public Object getType1() { + return new XType1() {}; + } + + public Object getType2() { + return new XType2() {}; + } + }; + } + + private final TestBed testBed; + } + + public interface XTransport extends XInterface { + Object getType1(); + + Object getType2(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("getType1", 0, 0), + new MethodTypeInfo("getType2", 1, 0) }; + } + + public interface XType1 extends XInterface { + TypeInfo[] UNOTYPEINFO = null; + } + + public interface XType2 extends XInterface { + TypeInfo[] UNOTYPEINFO = null; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug108825_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug108825_Test.java new file mode 100644 index 000000000000..9c7b84a960b3 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug108825_Test.java @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #108825#. + * + * <p>Bug #108825# "Java UNO Remote Bridge: Mapped-out Objects Not Held" shows + * that local objects that are mapped out via a remote bridge, but not held + * locally, might be garbage collected while there are still remote references + * to them. This test is not guaranteed to always work reliably, see comment in + * the code.</p> + */ +public final class Bug108825_Test extends ComplexTestCase { + public String getTestObjectName() { + return getClass().getName(); + } + + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + TestBed t = new TestBed(); + assure("test", t.execute(new Provider(t), true, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTest test = UnoRuntime.queryInterface( + XTest.class, getBridge(context).getInstance("Test")); + // Send the XObject that is held on the server side amidst two + // dummies that are not held on the server side; then wait for the + // dummies to be garbage collected, hoping that the XObject, if it + // is erroneously not held on the client side, will be garbage + // collected, too. Obviously, this is not guaranteed to always work + // (the VM might chose not to garbage collect the dummies, hanging + // the test forever; or the VM might chose to garbage collect the + // dummies but not the XObject, making the test pass erroneously). + test.offer(new Dummy(), new XObject() { public void call() {} }, + new Dummy()); + System.out.println("Client waiting for garbage collection..."); + for (;;) { + synchronized (lock) { + if (finalizedCount == 2) { + break; + } + } + test.remoteGc(); + gc(); + } + System.out.println("Client garbage collection done."); + test.notification(); + return true; + } + + private final class Dummy implements XDummy { + protected void finalize() { + synchronized (lock) { + ++finalizedCount; + } + } + } + + private final Object lock = new Object(); + private int finalizedCount = 0; + } + + // Make it as likely as possible that the VM reclaims all garbage: + private static void gc() { + System.gc(); + System.runFinalization(); + byte[] garbage = new byte[1024 * 1024]; + } + + private static final class Provider implements XInstanceProvider { + public Provider(TestBed testBed) { + this.testBed = testBed; + } + + public Object getInstance(String instanceName) { + return new XTest() { + public void offer(XDummy dummy1, XObject obj, XDummy dummy2) + { + this.obj = obj; + } + + public void remoteGc() { + gc(); + } + + public void notification() { + obj.call(); + testBed.serverDone(true); + } + + private XObject obj; + }; + } + + private final TestBed testBed; + } + + public interface XDummy extends XInterface { + TypeInfo[] UNOTYPEINFO = null; + } + + public interface XObject extends XInterface { + void call(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("call", 0, 0) }; + } + + public interface XTest extends XInterface { + void offer(XDummy dummy1, XObject obj, XDummy dummy2); + + void remoteGc(); + + void notification(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("offer", 0, 0), + new MethodTypeInfo("remoteGc", 1, 0), + new MethodTypeInfo("notification", 2, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug110892_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug110892_Test.java new file mode 100644 index 000000000000..322f8051ed60 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug110892_Test.java @@ -0,0 +1,124 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; +import util.WaitUnreachable; + +/** + * Test case for bug #110892#. + * + * <p>Bug #110892# "Java URP bridge holds objects indefinitely" applies to cases + * where an object is sent from server to client, then recursively back from + * client to server. In such a case, the client should not increment its + * internal reference count for the object, as the server will never send back a + * corresponding release message.</p> + * + * <p>This test has to detect whether the spawned client process fails to + * garbage-collect an object, which can not be done reliably. As an + * approximation, it waits for 10 sec and considers the process failing if it + * has not garbage-collected the object by then.</p> + */ +public final class Bug110892_Test extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure("test", + new TestBed().execute(new Provider(), false, Client.class, + 10000)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTest test = UnoRuntime.queryInterface( + XTest.class, getBridge(context).getInstance("Test")); + test.start(new ClientObject()); + synchronized (lock) { + unreachable.waitUnreachable(); + } + return true; + } + + private final class ClientObject implements XClientObject { + public void call(XServerObject server, XInterface object) { + synchronized (lock) { + unreachable = new WaitUnreachable(object); + } + server.call(object); + } + } + + private final Object lock = new Object(); + private WaitUnreachable unreachable = null; + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTest() { + public void start(XClientObject client) { + client.call( + new XServerObject() { + public void call(XInterface object) {} + }, + new XInterface() {}); + } + }; + } + } + + public interface XClientObject extends XInterface { + void call(XServerObject server, XInterface object); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("call", 0, 0) }; + } + + public interface XServerObject extends XInterface { + void call(XInterface object); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("call", 0, 0) }; + } + + public interface XTest extends XInterface { + void start(XClientObject client); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("start", 0, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug111153_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug111153_Test.java new file mode 100644 index 000000000000..351481cb4680 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug111153_Test.java @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #111153#. + * + * <P>Bug #111153# "jni_uno bridge sometimes fails to map objects + * correctly" describes that mapping a local object out with type XDerived and + * then mapping it back in with type XBase produces a proxy, instead of + * short-cutting to the local object.</P> + */ +public final class Bug111153_Test extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure("test", new TestBed().execute(new Provider(), false, + Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTransport t = UnoRuntime.queryInterface( + XTransport.class, getBridge(context).getInstance("Transport")); + XDerived d = new XDerived() {}; + t.setDerived(d); + return t.getBase() == d; + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTransport() { + public synchronized void setDerived(XDerived derived) { + this.derived = derived; + } + + public synchronized XBase getBase() { + return this.derived; + } + + private XDerived derived = null; + }; + } + } + + public interface XBase extends XInterface { + TypeInfo[] UNOTYPEINFO = null; + } + + public interface XDerived extends XBase { + TypeInfo[] UNOTYPEINFO = null; + } + + public interface XTransport extends XInterface { + void setDerived(XDerived derived); + + XBase getBase(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("setDerived", 0, 0), + new MethodTypeInfo("getBase", 1, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug114133_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug114133_Test.java new file mode 100644 index 000000000000..0049b966be1c --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug114133_Test.java @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; +import util.WaitUnreachable; + +/** + * Test case for bug #114133#. + * + * <p>Bug #114133# "Java UNO: UnoRuntime.getBride and disposed bridges." The + * client calls UnoRuntime.getBridge to get a bridge to the server, uses the + * bridge, waits until it terminates itself (when all bridged objects have been + * garbage-collected), then calls UnoRuntime.getBridge again. This must return + * a fresh, unterminated bridge.</p> + */ +public final class Bug114133_Test extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure( + "test", + new TestBed().execute(new Provider(), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + new WaitUnreachable(getBridge(context).getInstance("Test")). + waitUnreachable(); + new WaitUnreachable(getBridge(context).getInstance("Test")). + waitUnreachable(); + return true; + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XInterface() {}; + } + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug51323_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug51323_Test.java new file mode 100644 index 000000000000..bb13c55ee1ad --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug51323_Test.java @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XBridgeFactory; +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.connection.Connector; +import com.sun.star.connection.XConnection; +import com.sun.star.lib.TestBed; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; +import util.WaitUnreachable; + +/** + * Test case for bug #i51323#. + * + * <p>Bug #i51323# "jurt: BridgeFactory.createBridge creates bridge names." + * Make sure that multiple calls to BridgeFactory.getBridge with empty names + * create different bridges.</p> + */ +public final class Bug51323_Test extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure( + "test", + new TestBed().execute(new Provider(), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XConnection connection = + Connector.create(context).connect(getConnectionDescription()); + XBridgeFactory factory = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + return !UnoRuntime.areSame( + factory.createBridge( + "", getProtocolDescription(), connection, null), + factory.createBridge( + "", getProtocolDescription(), connection, null)); + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XInterface() {}; + } + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug92174_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug92174_Test.java new file mode 100644 index 000000000000..9c425a61fb2b --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug92174_Test.java @@ -0,0 +1,99 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +public final class Bug92174_Test extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure("test", + new TestBed().execute(new Provider(), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTransport t = UnoRuntime.queryInterface( + XTransport.class, getBridge(context).getInstance("Transport")); + t.setDerived(new XDerived() { + public void fn() {} + }); + t.getBase().fn(); + return true; + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTransport() { + public XBase getBase() { + return derived; + } + + public synchronized void setDerived(XDerived derived) { + this.derived = derived; + } + + private XDerived derived = null; + }; + } + } + + public interface XBase extends XInterface { + void fn(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("fn", 0, 0) }; + } + + public interface XDerived extends XBase { + TypeInfo[] UNOTYPEINFO = null; + } + + public interface XTransport extends XInterface { + XBase getBase(); + + void setDerived(XDerived derived); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("getBase", 0, 0), + new MethodTypeInfo("setDerived", 1, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug97697_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug97697_Test.java new file mode 100644 index 000000000000..34d98532688b --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug97697_Test.java @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lang.DisposedException; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #97697#. + * + * <p>Bug #97697# "GPF in java-uno bridge in bugdoc scenario" shows that sending + * a plain <code>Object</code> as an <code>Any</code> over the URP bridge lead + * to a <code>StackOverflowError</code> on the writer thread, which was silently + * discarded (and the bridge was not disposed).</p> + * + * <p>This test has to detect whether the spawned client process indeed hangs, + * which can not be done reliably. As an approximation, it waits for 10 sec and + * considers the process hanging if it has not completed by then.</p> + */ +public final class Bug97697_Test extends ComplexTestCase { + public String getTestObjectName() { + return getClass().getName(); + } + + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + TestBed t = new TestBed(); + assure("test", t.execute(new Provider(t), true, Client.class, 10000)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTransport transport = UnoRuntime.queryInterface( + XTransport.class, getBridge(context).getInstance("Transport")); + try { + transport.getAny(); + } catch (DisposedException e) { + return true; + } + return false; + } + } + + private static final class Provider implements XInstanceProvider { + public Provider(TestBed testBed) { + this.testBed = testBed; + } + + public Object getInstance(String instanceName) { + return new XTransport() { + public Object getAny() { + testBed.serverDone(true); + return new Object(); + } + }; + } + + private final TestBed testBed; + } + + public interface XTransport extends XInterface { + Object getAny(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("getAny", 0, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.idl b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.idl new file mode 100644 index 000000000000..491f82cc0a83 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.idl @@ -0,0 +1,37 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "com/sun/star/uno/XInterface.idl" + +module com { module sun { module star { module lib { module uno { +module bridges { module javaremote { + +struct Test98508Struct<T> { T member; }; + +interface Test98508Interface { Test98508Struct<long> get(); }; + +}; }; }; }; }; }; }; diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.java new file mode 100644 index 000000000000..82804cf22e67 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.java @@ -0,0 +1,104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lang.DisposedException; +import com.sun.star.lib.TestBed; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #98508#. + * + * <p>Bug #98508# "JAVA UNO bridge is not disposed when Exception occures during + * sendReply()" states that the server returning <code>null</code> instead of a + * valid <code>String</code> from <code>XServiceName.getServiceName</code> + * causes an exception when sending the reply, but this exception did not cause + * the bridge to be disposed, it rather caused both client and server to + * hang.</p> + * + * <p>Since null instead of a <code>String</code> no longer causes an exception + * in the bridge, this test has been redesigned to send a value of a wrong + * instantiated polymorphic struct type instead.</p> + * + * <p>This test has to detect whether the spawned client process indeed hangs, + * which can not be done reliably. As an approximation, it waits for 10 sec and + * considers the process hanging if it has not completed by then.</p> + */ +public final class Bug98508_Test extends ComplexTestCase { + public String getTestObjectName() { + return getClass().getName(); + } + + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + TestBed t = new TestBed(); + assure("test", t.execute(new Provider(t), true, Client.class, 10000)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + Test98508Interface ifc + = UnoRuntime.queryInterface( + Test98508Interface.class, + getBridge(context).getInstance("")); + try { + ifc.get(); + } catch (DisposedException e) { + return true; + } + return false; + } + } + + private static final class Provider implements XInstanceProvider { + public Provider(TestBed testBed) { + this.testBed = testBed; + } + + public Object getInstance(String instanceName) { + return new Test98508Interface() { + public Test98508Struct get() { + testBed.serverDone(true); + return new Test98508Struct(Boolean.FALSE); + } + }; + } + + private final TestBed testBed; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/MethodIdTest.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/MethodIdTest.java new file mode 100755 index 000000000000..39c8a0639b8f --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/MethodIdTest.java @@ -0,0 +1,473 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/** + * Test case for bug #111153#. + * + * <P>Bug #111153# "jni_uno bridge sometimes fails to map objects + * correctly" describes that mapping a local object out with type XDerived and + * then mapping it back in with type XBase produces a proxy, instead of + * short-cutting to the local object.</P> + */ +public final class MethodIdTest extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure( + "test", + new TestBed().execute(new Provider(), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTest t = UnoRuntime.queryInterface( + XTest.class, getBridge(context).getInstance("Test")); + return t.f129() == 129; + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTest() { + public int f0() { return 0; } + public int f1() { return 1; } + public int f2() { return 2; } + public int f3() { return 3; } + public int f4() { return 4; } + public int f5() { return 5; } + public int f6() { return 6; } + public int f7() { return 7; } + public int f8() { return 8; } + public int f9() { return 9; } + public int f10() { return 10; } + public int f11() { return 11; } + public int f12() { return 12; } + public int f13() { return 13; } + public int f14() { return 14; } + public int f15() { return 15; } + public int f16() { return 16; } + public int f17() { return 17; } + public int f18() { return 18; } + public int f19() { return 19; } + public int f20() { return 20; } + public int f21() { return 21; } + public int f22() { return 22; } + public int f23() { return 23; } + public int f24() { return 24; } + public int f25() { return 25; } + public int f26() { return 26; } + public int f27() { return 27; } + public int f28() { return 28; } + public int f29() { return 29; } + public int f30() { return 30; } + public int f31() { return 31; } + public int f32() { return 32; } + public int f33() { return 33; } + public int f34() { return 34; } + public int f35() { return 35; } + public int f36() { return 36; } + public int f37() { return 37; } + public int f38() { return 38; } + public int f39() { return 39; } + public int f40() { return 40; } + public int f41() { return 41; } + public int f42() { return 42; } + public int f43() { return 43; } + public int f44() { return 44; } + public int f45() { return 45; } + public int f46() { return 46; } + public int f47() { return 47; } + public int f48() { return 48; } + public int f49() { return 49; } + public int f50() { return 50; } + public int f51() { return 51; } + public int f52() { return 52; } + public int f53() { return 53; } + public int f54() { return 54; } + public int f55() { return 55; } + public int f56() { return 56; } + public int f57() { return 57; } + public int f58() { return 58; } + public int f59() { return 59; } + public int f60() { return 60; } + public int f61() { return 61; } + public int f62() { return 62; } + public int f63() { return 63; } + public int f64() { return 64; } + public int f65() { return 65; } + public int f66() { return 66; } + public int f67() { return 67; } + public int f68() { return 68; } + public int f69() { return 69; } + public int f70() { return 70; } + public int f71() { return 71; } + public int f72() { return 72; } + public int f73() { return 73; } + public int f74() { return 74; } + public int f75() { return 75; } + public int f76() { return 76; } + public int f77() { return 77; } + public int f78() { return 78; } + public int f79() { return 79; } + public int f80() { return 80; } + public int f81() { return 81; } + public int f82() { return 82; } + public int f83() { return 83; } + public int f84() { return 84; } + public int f85() { return 85; } + public int f86() { return 86; } + public int f87() { return 87; } + public int f88() { return 88; } + public int f89() { return 89; } + public int f90() { return 90; } + public int f91() { return 91; } + public int f92() { return 92; } + public int f93() { return 93; } + public int f94() { return 94; } + public int f95() { return 95; } + public int f96() { return 96; } + public int f97() { return 97; } + public int f98() { return 98; } + public int f99() { return 99; } + public int f100() { return 100; } + public int f101() { return 101; } + public int f102() { return 102; } + public int f103() { return 103; } + public int f104() { return 104; } + public int f105() { return 105; } + public int f106() { return 106; } + public int f107() { return 107; } + public int f108() { return 108; } + public int f109() { return 109; } + public int f110() { return 110; } + public int f111() { return 111; } + public int f112() { return 112; } + public int f113() { return 113; } + public int f114() { return 114; } + public int f115() { return 115; } + public int f116() { return 116; } + public int f117() { return 117; } + public int f118() { return 118; } + public int f119() { return 119; } + public int f120() { return 120; } + public int f121() { return 121; } + public int f122() { return 122; } + public int f123() { return 123; } + public int f124() { return 124; } + public int f125() { return 125; } + public int f126() { return 126; } + public int f127() { return 127; } + public int f128() { return 128; } + public int f129() { return 129; } + public int f130() { return 130; } + }; + } + } + + public interface XTest extends XInterface { + int f0(); + int f1(); + int f2(); + int f3(); + int f4(); + int f5(); + int f6(); + int f7(); + int f8(); + int f9(); + int f10(); + int f11(); + int f12(); + int f13(); + int f14(); + int f15(); + int f16(); + int f17(); + int f18(); + int f19(); + int f20(); + int f21(); + int f22(); + int f23(); + int f24(); + int f25(); + int f26(); + int f27(); + int f28(); + int f29(); + int f30(); + int f31(); + int f32(); + int f33(); + int f34(); + int f35(); + int f36(); + int f37(); + int f38(); + int f39(); + int f40(); + int f41(); + int f42(); + int f43(); + int f44(); + int f45(); + int f46(); + int f47(); + int f48(); + int f49(); + int f50(); + int f51(); + int f52(); + int f53(); + int f54(); + int f55(); + int f56(); + int f57(); + int f58(); + int f59(); + int f60(); + int f61(); + int f62(); + int f63(); + int f64(); + int f65(); + int f66(); + int f67(); + int f68(); + int f69(); + int f70(); + int f71(); + int f72(); + int f73(); + int f74(); + int f75(); + int f76(); + int f77(); + int f78(); + int f79(); + int f80(); + int f81(); + int f82(); + int f83(); + int f84(); + int f85(); + int f86(); + int f87(); + int f88(); + int f89(); + int f90(); + int f91(); + int f92(); + int f93(); + int f94(); + int f95(); + int f96(); + int f97(); + int f98(); + int f99(); + int f100(); + int f101(); + int f102(); + int f103(); + int f104(); + int f105(); + int f106(); + int f107(); + int f108(); + int f109(); + int f110(); + int f111(); + int f112(); + int f113(); + int f114(); + int f115(); + int f116(); + int f117(); + int f118(); + int f119(); + int f120(); + int f121(); + int f122(); + int f123(); + int f124(); + int f125(); + int f126(); + int f127(); + int f128(); + int f129(); + int f130(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("f0", 0, 0), + new MethodTypeInfo("f1", 1, 0), + new MethodTypeInfo("f2", 2, 0), + new MethodTypeInfo("f3", 3, 0), + new MethodTypeInfo("f4", 4, 0), + new MethodTypeInfo("f5", 5, 0), + new MethodTypeInfo("f6", 6, 0), + new MethodTypeInfo("f7", 7, 0), + new MethodTypeInfo("f8", 8, 0), + new MethodTypeInfo("f9", 9, 0), + new MethodTypeInfo("f10", 10, 0), + new MethodTypeInfo("f11", 11, 0), + new MethodTypeInfo("f12", 12, 0), + new MethodTypeInfo("f13", 13, 0), + new MethodTypeInfo("f14", 14, 0), + new MethodTypeInfo("f15", 15, 0), + new MethodTypeInfo("f16", 16, 0), + new MethodTypeInfo("f17", 17, 0), + new MethodTypeInfo("f18", 18, 0), + new MethodTypeInfo("f19", 19, 0), + new MethodTypeInfo("f20", 20, 0), + new MethodTypeInfo("f21", 21, 0), + new MethodTypeInfo("f22", 22, 0), + new MethodTypeInfo("f23", 23, 0), + new MethodTypeInfo("f24", 24, 0), + new MethodTypeInfo("f25", 25, 0), + new MethodTypeInfo("f26", 26, 0), + new MethodTypeInfo("f27", 27, 0), + new MethodTypeInfo("f28", 28, 0), + new MethodTypeInfo("f29", 29, 0), + new MethodTypeInfo("f30", 30, 0), + new MethodTypeInfo("f31", 31, 0), + new MethodTypeInfo("f32", 32, 0), + new MethodTypeInfo("f33", 33, 0), + new MethodTypeInfo("f34", 34, 0), + new MethodTypeInfo("f35", 35, 0), + new MethodTypeInfo("f36", 36, 0), + new MethodTypeInfo("f37", 37, 0), + new MethodTypeInfo("f38", 38, 0), + new MethodTypeInfo("f39", 39, 0), + new MethodTypeInfo("f40", 40, 0), + new MethodTypeInfo("f41", 41, 0), + new MethodTypeInfo("f42", 42, 0), + new MethodTypeInfo("f43", 43, 0), + new MethodTypeInfo("f44", 44, 0), + new MethodTypeInfo("f45", 45, 0), + new MethodTypeInfo("f46", 46, 0), + new MethodTypeInfo("f47", 47, 0), + new MethodTypeInfo("f48", 48, 0), + new MethodTypeInfo("f49", 49, 0), + new MethodTypeInfo("f50", 50, 0), + new MethodTypeInfo("f51", 51, 0), + new MethodTypeInfo("f52", 52, 0), + new MethodTypeInfo("f53", 53, 0), + new MethodTypeInfo("f54", 54, 0), + new MethodTypeInfo("f55", 55, 0), + new MethodTypeInfo("f56", 56, 0), + new MethodTypeInfo("f57", 57, 0), + new MethodTypeInfo("f58", 58, 0), + new MethodTypeInfo("f59", 59, 0), + new MethodTypeInfo("f60", 60, 0), + new MethodTypeInfo("f61", 61, 0), + new MethodTypeInfo("f62", 62, 0), + new MethodTypeInfo("f63", 63, 0), + new MethodTypeInfo("f64", 64, 0), + new MethodTypeInfo("f65", 65, 0), + new MethodTypeInfo("f66", 66, 0), + new MethodTypeInfo("f67", 67, 0), + new MethodTypeInfo("f68", 68, 0), + new MethodTypeInfo("f69", 69, 0), + new MethodTypeInfo("f70", 70, 0), + new MethodTypeInfo("f71", 71, 0), + new MethodTypeInfo("f72", 72, 0), + new MethodTypeInfo("f73", 73, 0), + new MethodTypeInfo("f74", 74, 0), + new MethodTypeInfo("f75", 75, 0), + new MethodTypeInfo("f76", 76, 0), + new MethodTypeInfo("f77", 77, 0), + new MethodTypeInfo("f78", 78, 0), + new MethodTypeInfo("f79", 79, 0), + new MethodTypeInfo("f80", 80, 0), + new MethodTypeInfo("f81", 81, 0), + new MethodTypeInfo("f82", 82, 0), + new MethodTypeInfo("f83", 83, 0), + new MethodTypeInfo("f84", 84, 0), + new MethodTypeInfo("f85", 85, 0), + new MethodTypeInfo("f86", 86, 0), + new MethodTypeInfo("f87", 87, 0), + new MethodTypeInfo("f88", 88, 0), + new MethodTypeInfo("f89", 89, 0), + new MethodTypeInfo("f90", 90, 0), + new MethodTypeInfo("f91", 91, 0), + new MethodTypeInfo("f92", 92, 0), + new MethodTypeInfo("f93", 93, 0), + new MethodTypeInfo("f94", 94, 0), + new MethodTypeInfo("f95", 95, 0), + new MethodTypeInfo("f96", 96, 0), + new MethodTypeInfo("f97", 97, 0), + new MethodTypeInfo("f98", 98, 0), + new MethodTypeInfo("f99", 99, 0), + new MethodTypeInfo("f100", 100, 0), + new MethodTypeInfo("f101", 101, 0), + new MethodTypeInfo("f102", 102, 0), + new MethodTypeInfo("f103", 103, 0), + new MethodTypeInfo("f104", 104, 0), + new MethodTypeInfo("f105", 105, 0), + new MethodTypeInfo("f106", 106, 0), + new MethodTypeInfo("f107", 107, 0), + new MethodTypeInfo("f108", 108, 0), + new MethodTypeInfo("f109", 109, 0), + new MethodTypeInfo("f110", 110, 0), + new MethodTypeInfo("f111", 111, 0), + new MethodTypeInfo("f112", 112, 0), + new MethodTypeInfo("f113", 113, 0), + new MethodTypeInfo("f114", 114, 0), + new MethodTypeInfo("f115", 115, 0), + new MethodTypeInfo("f116", 116, 0), + new MethodTypeInfo("f117", 117, 0), + new MethodTypeInfo("f118", 118, 0), + new MethodTypeInfo("f119", 119, 0), + new MethodTypeInfo("f120", 120, 0), + new MethodTypeInfo("f121", 121, 0), + new MethodTypeInfo("f122", 122, 0), + new MethodTypeInfo("f123", 123, 0), + new MethodTypeInfo("f124", 124, 0), + new MethodTypeInfo("f125", 125, 0), + new MethodTypeInfo("f126", 126, 0), + new MethodTypeInfo("f127", 127, 0), + new MethodTypeInfo("f128", 128, 0), + new MethodTypeInfo("f129", 129, 0), + new MethodTypeInfo("f130", 130, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.idl b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.idl new file mode 100644 index 000000000000..68330567d405 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.idl @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "com/sun/star/uno/XInterface.idl" + +module com { module sun { module star { module lib { module uno { +module bridges { module javaremote { + +enum TestEnum { VALUE1 = 100, VALUE2 = -100 }; + +struct TestPolyStruct<T> { T member; }; + +interface TestTransport { + TestPolyStruct<boolean> transportBoolean([in] TestPolyStruct<boolean> arg); + TestPolyStruct<byte> transportByte([in] TestPolyStruct<byte> arg); + TestPolyStruct<short> transportShort([in] TestPolyStruct<short> arg); + TestPolyStruct<long> transportLong([in] TestPolyStruct<long> arg); + TestPolyStruct<hyper> transportHyper([in] TestPolyStruct<hyper> arg); + TestPolyStruct<float> transportFloat([in] TestPolyStruct<float> arg); + TestPolyStruct<double> transportDouble([in] TestPolyStruct<double> arg); + TestPolyStruct<char> transportChar([in] TestPolyStruct<char> arg); + TestPolyStruct<string> transportString([in] TestPolyStruct<string> arg); + TestPolyStruct<type> transportType([in] TestPolyStruct<type> arg); + TestPolyStruct<any> transportAny([in] TestPolyStruct<any> arg); + TestPolyStruct<TestEnum> transportEnum([in] TestPolyStruct<TestEnum> arg); +}; + +}; }; }; }; }; }; }; diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.java new file mode 100644 index 000000000000..ebf1ed57bc2c --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.java @@ -0,0 +1,260 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MemberTypeInfo; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.ParameterTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.Any; +import com.sun.star.uno.Type; +import com.sun.star.uno.TypeClass; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +public final class PolyStructTest extends ComplexTestCase { + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure( + "test", + new TestBed().execute(new Provider(), false, Client.class, 0)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + TestTransport t = UnoRuntime.queryInterface( + TestTransport.class, getBridge(context).getInstance("")); + + assertEquals( + Boolean.FALSE, t.transportBoolean(new TestPolyStruct()).member); + assertEquals( + Boolean.FALSE, + t.transportBoolean(new TestPolyStruct(Boolean.FALSE)).member); + assertEquals( + Boolean.TRUE, + t.transportBoolean(new TestPolyStruct(Boolean.TRUE)).member); + + assertEquals( + new Byte((byte) 0), + t.transportByte(new TestPolyStruct()).member); + assertEquals( + new Byte(Byte.MIN_VALUE), + t.transportByte( + new TestPolyStruct(new Byte(Byte.MIN_VALUE))).member); + assertEquals( + new Byte(Byte.MAX_VALUE), + t.transportByte( + new TestPolyStruct(new Byte(Byte.MAX_VALUE))).member); + + assertEquals( + new Short((short) 0), + t.transportShort(new TestPolyStruct()).member); + assertEquals( + new Short(Short.MIN_VALUE), + t.transportShort( + new TestPolyStruct(new Short(Short.MIN_VALUE))).member); + assertEquals( + new Short(Short.MAX_VALUE), + t.transportShort( + new TestPolyStruct(new Short(Short.MAX_VALUE))).member); + + assertEquals( + new Integer(0), t.transportLong(new TestPolyStruct()).member); + assertEquals( + new Integer(Integer.MIN_VALUE), + t.transportLong( + new TestPolyStruct(new Integer(Integer.MIN_VALUE))).member); + assertEquals( + new Integer(Integer.MAX_VALUE), + t.transportLong( + new TestPolyStruct(new Integer(Integer.MAX_VALUE))).member); + + assertEquals( + new Long(0L), t.transportHyper(new TestPolyStruct()).member); + assertEquals( + new Long(Long.MIN_VALUE), + t.transportHyper( + new TestPolyStruct(new Long(Long.MIN_VALUE))).member); + assertEquals( + new Long(Long.MAX_VALUE), + t.transportHyper( + new TestPolyStruct(new Long(Long.MAX_VALUE))).member); + + assertEquals( + new Float(0.0f), t.transportFloat(new TestPolyStruct()).member); + assertEquals( + new Float(Float.MIN_VALUE), + t.transportFloat( + new TestPolyStruct(new Float(Float.MIN_VALUE))).member); + assertEquals( + new Float(Float.MAX_VALUE), + t.transportFloat( + new TestPolyStruct(new Float(Float.MAX_VALUE))).member); + + assertEquals( + new Double(0.0), + t.transportDouble(new TestPolyStruct()).member); + assertEquals( + new Double(Double.MIN_VALUE), + t.transportDouble( + new TestPolyStruct(new Double(Double.MIN_VALUE))).member); + assertEquals( + new Double(Double.MAX_VALUE), + t.transportDouble( + new TestPolyStruct(new Double(Double.MAX_VALUE))).member); + + assertEquals( + new Character(Character.MIN_VALUE), + t.transportChar(new TestPolyStruct()).member); + assertEquals( + new Character(Character.MIN_VALUE), + t.transportChar( + new TestPolyStruct( + new Character(Character.MIN_VALUE))).member); + assertEquals( + new Character(Character.MAX_VALUE), + t.transportChar( + new TestPolyStruct( + new Character(Character.MAX_VALUE))).member); + + assertEquals("", t.transportString(new TestPolyStruct()).member); + assertEquals( + "ABC", t.transportString(new TestPolyStruct("ABC")).member); + + assertEquals( + Type.VOID, t.transportType(new TestPolyStruct()).member); + assertEquals( + new Type( + "[]com.sun.star.lib.uno.bridges.javaremote.TestPolyStruct" + + "<long>"), + t.transportType( + new TestPolyStruct( + new Type( + "[]com.sun.star.lib.uno.bridges.javaremote." + + "TestPolyStruct<long>"))).member); + + assertEquals(null, t.transportAny(new TestPolyStruct()).member); + assertEquals( + Any.VOID, t.transportAny(new TestPolyStruct(Any.VOID)).member); + assertEquals(null, t.transportAny(new TestPolyStruct(null)).member); + assertEquals( + new Any(Type.UNSIGNED_LONG, new Integer(5)), + t.transportAny( + new TestPolyStruct( + new Any(Type.UNSIGNED_LONG, new Integer(5)))).member); + + assertEquals( + TestEnum.VALUE1, t.transportEnum(new TestPolyStruct()).member); + assertEquals( + TestEnum.VALUE1, + t.transportEnum(new TestPolyStruct(TestEnum.VALUE1)).member); + assertEquals( + TestEnum.VALUE2, + t.transportEnum(new TestPolyStruct(TestEnum.VALUE2)).member); + + return success; + } + + private void assertEquals(Object expected, Object actual) { + if (!(expected == null ? actual == null : expected.equals(actual))) + { + new RuntimeException( + "failed; expected " + expected + ", got " + actual). + printStackTrace(); + success = false; + } + } + + private boolean success = true; + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new TestTransport() { + public TestPolyStruct transportBoolean(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportByte(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportShort(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportLong(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportHyper(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportFloat(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportDouble(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportChar(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportString(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportType(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportAny(TestPolyStruct s) { + return s; + } + + public TestPolyStruct transportEnum(TestPolyStruct s) { + return s; + } + }; + } + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/StopMessageDispatcherTest.java b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/StopMessageDispatcherTest.java new file mode 100644 index 000000000000..2456d681563d --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/StopMessageDispatcherTest.java @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.lib.uno.bridges.javaremote; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lang.DisposedException; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import complexlib.ComplexTestCase; + +/* This test has to detect whether the spawned client process hangs, which can + * not be done reliably. As an approximation, it waits for 10 sec and considers + * the process hanging if it has not terminated by then. + */ +public final class StopMessageDispatcherTest extends ComplexTestCase { + public StopMessageDispatcherTest() {} + + public String[] getTestMethodNames() { + return new String[] { "test" }; + } + + public void test() throws Exception { + assure( + "test", + new TestBed().execute(new Provider(), false, Client.class, 10000)); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTest test = UnoRuntime.queryInterface( + XTest.class, getBridge(context).getInstance("Test")); + Thread[] threads = new Thread[101]; + int n = Thread.enumerate(threads); + if (n > 100) { + System.err.println("ERROR: too many threads"); + return false; + } + boolean stopped = false; + for (int i = 0; i < n; ++i) { + if (threads[i].getName().equals("MessageDispatcher")) { + threads[i].stop(); + stopped = true; + break; + } + } + if (!stopped) { + System.err.println("ERROR: thread not found"); + return false; + } + try { + test.call(); + System.err.println("ERROR: no DisposedException"); + return false; + } catch (DisposedException e) { + return true; + } + } + + private Client() {} + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTest() { + public void call() {} + }; + } + } + + public interface XTest extends XInterface { + void call(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("call", 0, 0) }; + } +} diff --git a/bridges/test/com/sun/star/lib/uno/bridges/java_remote/makefile.mk b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/makefile.mk new file mode 100644 index 000000000000..e532a012c615 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ := ..$/..$/..$/..$/..$/..$/..$/.. +PRJNAME := bridges +TARGET := test_com_sun_star_lib_uno_bridges_javaremote + +PACKAGE := com$/sun$/star$/lib$/uno$/bridges$/javaremote +JAVATESTFILES := \ + Bug51323_Test.java \ + Bug92174_Test.java \ + Bug97697_Test.java \ + Bug98508_Test.java \ + Bug107753_Test.java \ + Bug108825_Test.java \ + Bug110892_Test.java \ + Bug111153_Test.java \ + Bug114133_Test.java \ + MethodIdTest.java \ + PolyStructTest.java \ + StopMessageDispatcherTest.java +IDLTESTFILES := \ + Bug98508_Test.idl \ + PolyStructTest.idl +JARFILES := juh.jar jurt.jar ridl.jar + +.INCLUDE: javaunittest.mk diff --git a/bridges/test/inter_libs_exc/inter.cxx b/bridges/test/inter_libs_exc/inter.cxx new file mode 100644 index 000000000000..56966388f09e --- /dev/null +++ b/bridges/test/inter_libs_exc/inter.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include "share.h" + +#include <rtl/string.hxx> +#include <osl/module.hxx> + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +extern "C" int main( int argc, char const * argv [] ) +{ +#ifdef SAL_W32 +#define SAL_DLLPREFIX "" +#endif + Module mod_starter( + OUSTR(SAL_DLLPREFIX"starter"SAL_DLLEXTENSION), + SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL ); + Module mod_thrower( + OUSTR(SAL_DLLPREFIX"thrower"SAL_DLLEXTENSION), + SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL ); + + typedef t_throws_exc (SAL_CALL * t_get_thrower)(); + t_get_thrower get_thrower = (t_get_thrower)mod_thrower.getSymbol( OUSTR("get_thrower") ); + t_throws_exc thrower = (*get_thrower)(); + + typedef void (SAL_CALL * t_starter)( t_throws_exc ); + t_starter start = (t_starter)mod_starter.getSymbol( OUSTR("start") ); + + (*start)( thrower ); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/inter_libs_exc/makefile.mk b/bridges/test/inter_libs_exc/makefile.mk new file mode 100644 index 000000000000..7f9ff0512e24 --- /dev/null +++ b/bridges/test/inter_libs_exc/makefile.mk @@ -0,0 +1,80 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=bridges +TARGET=inter +LIBTARGET=NO +TARGETTYPE=CUI +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +UNOUCRDEP=$(SOLARBINDIR)$/udkapi.rdb +UNOUCRRDB=$(SOLARBINDIR)$/udkapi.rdb + +# output directory (one dir for each project) +UNOUCROUT=$(OUT)$/inc$/$(TARGET) + +# adding to inludeoath +INCPRE+=$(UNOUCROUT) + +UNOTYPESTYPES := \ + com.sun.star.lang.IllegalArgumentException \ + com.sun.star.uno.DeploymentException + +SLOFILES=$(SLO)$/starter.obj $(SLO)$/thrower.obj + +SHL1TARGET=starter +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(SHL1TARGET) +SHL1OBJS=$(SLO)$/starter.obj +DEF1NAME=$(SHL1TARGET) +SHL1STDLIBS+= $(CPPULIB) $(SALLIB) +SHL1VERSIONMAP=$(SHL1TARGET).map + +SHL2TARGET=thrower +SHL2DEF=$(MISC)$/$(SHL2TARGET).def +SHL2IMPLIB=i$(SHL2TARGET) +SHL2OBJS=$(SLO)$/thrower.obj +DEF2NAME=$(SHL2TARGET) +SHL2STDLIBS+= $(CPPULIB) $(SALLIB) +SHL2VERSIONMAP=$(SHL2TARGET).map + +OBJFILES=$(OBJ)$/inter.obj +APP1TARGET=inter +APP1OBJS=$(OBJ)$/inter.obj +APP1STDLIBS+=\ + $(SALLIB) + +.INCLUDE : target.mk + diff --git a/bridges/test/inter_libs_exc/share.h b/bridges/test/inter_libs_exc/share.h new file mode 100644 index 000000000000..be06619abf76 --- /dev/null +++ b/bridges/test/inter_libs_exc/share.h @@ -0,0 +1,10 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/uno/DeploymentException.hpp> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +typedef void (SAL_CALL * t_throws_exc)(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/inter_libs_exc/starter.cxx b/bridges/test/inter_libs_exc/starter.cxx new file mode 100644 index 000000000000..e19e83990979 --- /dev/null +++ b/bridges/test/inter_libs_exc/starter.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include "share.h" + + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +static void some_more( t_throws_exc p ) +{ + (*p)(); +} + +extern "C" void SAL_CALL start( t_throws_exc p ) +{ + try + { + some_more( p ); + } + catch (lang::IllegalArgumentException & exc) + { + OString msg( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + printf( "starter.cxx: caught IllegalArgumentException: %s\n", msg.getStr() ); + } + catch (Exception & exc) + { + OString msg( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + printf( "starter.cxx: caught some UNO exc: %s\n", msg.getStr() ); + } + catch (...) + { + printf( "starter.cxx: caught something\n" ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/inter_libs_exc/starter.map b/bridges/test/inter_libs_exc/starter.map new file mode 100644 index 000000000000..69bf77c0a34b --- /dev/null +++ b/bridges/test/inter_libs_exc/starter.map @@ -0,0 +1,7 @@ +UDK_3_0_0 { + global: + start; + local: + *; +}; + diff --git a/bridges/test/inter_libs_exc/thrower.cxx b/bridges/test/inter_libs_exc/thrower.cxx new file mode 100644 index 000000000000..d490e5d7b084 --- /dev/null +++ b/bridges/test/inter_libs_exc/thrower.cxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "share.h" + + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +static void SAL_CALL throws_exc() +{ + throw lang::IllegalArgumentException( + OUSTR("bla"), Reference< XInterface >(), 0 ); +} + +extern "C" t_throws_exc SAL_CALL get_thrower() +{ + return throws_exc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/inter_libs_exc/thrower.map b/bridges/test/inter_libs_exc/thrower.map new file mode 100644 index 000000000000..163d434e0121 --- /dev/null +++ b/bridges/test/inter_libs_exc/thrower.map @@ -0,0 +1,7 @@ +UDK_3_0_0 { + global: + get_thrower; + local: + *; +}; + diff --git a/bridges/test/java_uno/acquire/TestAcquire.java b/bridges/test/java_uno/acquire/TestAcquire.java new file mode 100644 index 000000000000..0314e6bfcf9d --- /dev/null +++ b/bridges/test/java_uno/acquire/TestAcquire.java @@ -0,0 +1,304 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.javauno.acquire; + +import com.sun.star.bridge.UnoUrlResolver; +import com.sun.star.bridge.XBridgeFactory; +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.comp.helper.Bootstrap; +import com.sun.star.connection.Acceptor; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.lib.uno.helper.UnoUrl; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import util.WaitUnreachable; + +public final class TestAcquire { + public static void main(String[] arguments) throws Exception { + // - arguments[0] must be "client" or "server" + // - arguments[1] must be the UNO URL to connect to (client) or accept + // on (server) + XComponentContext context + = Bootstrap.createInitialComponentContext(null); + if (arguments[0].equals("client")) { + execClient(context, arguments[1]); + } else { + execServer(context, arguments[1]); + } + } + + private static void assertNotNull(Object obj) { + if (obj == null) { + throw new RuntimeException("assertNotNull failed"); + } + } + + private static void receive(Object obj) { + assertNotNull(obj); + WaitUnreachable.ensureFinalization(obj); + } + + private static void execClient(XComponentContext context, String url) + throws Exception + { + XTest test = UnoRuntime.queryInterface( + XTest.class, UnoUrlResolver.create(context).resolve(url)); + + WaitUnreachable u; + + u = new WaitUnreachable(new XInterface() {}); + test.setInterfaceToInterface((XInterface) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + u = new WaitUnreachable(new XBase() {}); + test.setInterfaceToInterface((XBase) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + test.setInterfaceToInterface((XDerived) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XBase() {}); + test.setBaseToInterface((XBase) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + test.setBaseToInterface((XDerived) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + test.setDerivedToInterface((XDerived) u.get()); + receive(test.getInterfaceFromInterface()); + test.clearInterface(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XBase() {}); + test.setBaseToBase((XBase) u.get()); + receive(test.getInterfaceFromBase()); + receive(test.getBaseFromBase()); + test.clearBase(); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + test.setBaseToBase((XDerived) u.get()); + receive(test.getInterfaceFromBase()); + receive(test.getBaseFromBase()); + test.clearBase(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + test.setDerivedToBase((XDerived) u.get()); + receive(test.getInterfaceFromBase()); + receive(test.getBaseFromBase()); + test.clearBase(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + test.setDerivedToDerived((XDerived) u.get()); + receive(test.getInterfaceFromDerived()); + receive(test.getBaseFromDerived()); + receive(test.getDerivedFromDerived()); + test.clearDerived(); + u.waitUnreachable(); + + u = new WaitUnreachable(new XInterface() {}); + receive(test.roundTripInterfaceToInterface((XInterface) u.get())); + u.waitUnreachable(); + u = new WaitUnreachable(new XBase() {}); + receive(test.roundTripInterfaceToInterface((XBase) u.get())); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripInterfaceToInterface((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(new XBase() {}); + receive(test.roundTripBaseToInterface((XBase) u.get())); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripBaseToInterface((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripDerivedToInterface((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(new XBase() {}); + receive(test.roundTripBaseToBase((XBase) u.get())); + u.waitUnreachable(); + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripBaseToBase((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripDerivedToBase((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(new XDerived() {}); + receive(test.roundTripDerivedToDerived((XDerived) u.get())); + u.waitUnreachable(); + + u = new WaitUnreachable(test); + test = null; + u.waitUnreachable(); + System.out.println( + "Client and server both cleanly terminate now: Success"); + } + + private static void execServer(XComponentContext context, String url) + throws Exception + { + XAcceptor acceptor = Acceptor.create(context); + XBridgeFactory factory = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + UnoUrl unoUrl = UnoUrl.parseUnoUrl(url); + System.out.println("Server: Accepting..."); + XConnection connection = acceptor.accept( + unoUrl.getConnectionAndParametersAsString()); + System.out.println("Server: ...connected..."); + factory.createBridge( + "", unoUrl.getProtocolAndParametersAsString(), connection, + new Provider()); + System.out.println("Server: ...bridged."); + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTest() { + public void setInterfaceToInterface(Object obj) { + iface = obj; + } + + public void setBaseToInterface(XBase obj) { + iface = obj; + } + + public void setDerivedToInterface(XDerived obj) { + iface = obj; + } + + public Object getInterfaceFromInterface() { + return iface; + } + + public void clearInterface() { + WaitUnreachable u = new WaitUnreachable(iface); + iface = null; + u.waitUnreachable(); + } + + public void setBaseToBase(XBase obj) { + base = obj; + } + + public void setDerivedToBase(XDerived obj) { + base = obj; + } + + public Object getInterfaceFromBase() { + return base; + } + + public XBase getBaseFromBase() { + return base; + } + + public void clearBase() { + WaitUnreachable u = new WaitUnreachable(base); + base = null; + u.waitUnreachable(); + } + + public void setDerivedToDerived(XDerived obj) { + derived = obj; + } + + public Object getInterfaceFromDerived() { + return derived; + } + + public XBase getBaseFromDerived() { + return derived; + } + + public XDerived getDerivedFromDerived() { + return derived; + } + + public void clearDerived() { + WaitUnreachable u = new WaitUnreachable(derived); + derived = null; + u.waitUnreachable(); + } + + public Object roundTripInterfaceToInterface(Object obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + public Object roundTripBaseToInterface(XBase obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + public Object roundTripDerivedToInterface(XDerived obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + public XBase roundTripBaseToBase(XBase obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + public XBase roundTripDerivedToBase(XDerived obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + public XDerived roundTripDerivedToDerived(XDerived obj) { + WaitUnreachable.ensureFinalization(obj); + return obj; + } + + private Object iface; + private XBase base; + private XDerived derived; + }; + } + } +} diff --git a/bridges/test/java_uno/acquire/makefile.mk b/bridges/test/java_uno/acquire/makefile.mk new file mode 100644 index 000000000000..def12dd53c49 --- /dev/null +++ b/bridges/test/java_uno/acquire/makefile.mk @@ -0,0 +1,117 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ := ..$/..$/.. +PRJNAME := bridges + +TARGET := test_javauno_acquire +PACKAGE := test$/javauno$/acquire + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk + +DLLPRE = # no leading "lib" on .so files +INCPRE += $(MISC)$/$(TARGET)$/inc + +SLOFILES = $(SLO)$/testacquire.obj + +SHL1TARGET = testacquire.uno +SHL1OBJS = $(SLOFILES) +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1IMPLIB = itestacquire + +JAVAFILES = TestAcquire.java +JARFILES = OOoRunner.jar juh.jar jurt.jar ridl.jar + +.INCLUDE: target.mk + +ALLTAR: \ + $(BIN)$/testacquire-java-client \ + $(BIN)$/testacquire-java-server \ + $(BIN)$/testacquire-native-client \ + $(BIN)$/testacquire-native-server + +.IF "$(GUI)" == "WNT" +GIVE_EXEC_RIGHTS = @echo +.ELSE # GUI, WNT +GIVE_EXEC_RIGHTS = chmod +x +.ENDIF # GUI, WNT + +EXEC_CLASSPATH_TMP = $(foreach,i,$(JARFILES) $(SOLARBINDIR)$/$i) +EXEC_CLASSPATH = \ + $(strip $(subst,!,$(PATH_SEPERATOR) $(EXEC_CLASSPATH_TMP:s/ /!/))) + +$(BIN)$/$(TARGET).rdb: types.idl + - rm $@ + - $(MKDIR) $(MISC)$/$(TARGET) + - $(MKDIR) $(MISC)$/$(TARGET)$/inc + $(IDLC) -I$(SOLARIDLDIR) -O$(MISC)$/$(TARGET) $< + $(REGMERGE) $@ /UCR $(MISC)$/$(TARGET)$/types.urd + $(CPPUMAKER) -BUCR -C -O$(MISC)$/$(TARGET)$/inc $@ -X$(SOLARBINDIR)$/types.rdb + $(JAVAMAKER) -BUCR -nD -O$(CLASSDIR) $@ -X$(SOLARBINDIR)$/types.rdb + $(REGMERGE) $@ / $(SOLARBINDIR)$/types.rdb + $(REGCOMP) -register -r $@ -c acceptor.uno$(DLLPOST) \ + -c bridgefac.uno$(DLLPOST) -c connector.uno$(DLLPOST) \ + -c remotebridge.uno$(DLLPOST) -c uuresolver.uno$(DLLPOST) + +$(SLOFILES) $(JAVACLASSFILES): $(BIN)$/$(TARGET).rdb + +# Use "127.0.0.1" instead of "localhost", see #i32281#: +TEST_JAVAUNO_ACQUIRE_UNO_URL := \ + \"'uno:socket,host=127.0.0.1,port=2002;urp;test'\" + +$(BIN)$/testacquire-java-client: + echo java -classpath \ + ..$/class$/test$(PATH_SEPERATOR)..$/class$(PATH_SEPERATOR)\ +..$/class$/java_uno.jar$(PATH_SEPERATOR)$(EXEC_CLASSPATH) \ + test.javauno.acquire.TestAcquire client \ + $(TEST_JAVAUNO_ACQUIRE_UNO_URL) > $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(BIN)$/testacquire-java-server: + echo java -classpath \ + ..$/class$/test$(PATH_SEPERATOR)..$/class$(PATH_SEPERATOR)\ +..$/class$/java_uno.jar$(PATH_SEPERATOR)$(EXEC_CLASSPATH) \ + test.javauno.acquire.TestAcquire server \ + $(TEST_JAVAUNO_ACQUIRE_UNO_URL) > $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(BIN)$/testacquire-native-client: + echo '$(AUGMENT_LIBRARY_PATH)' uno \ + -c com.sun.star.test.bridges.testacquire.impl \ + -l ../lib/$(SHL1TARGETN:f) -ro $(TARGET).rdb -- \ + $(TEST_JAVAUNO_ACQUIRE_UNO_URL) > $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(BIN)$/testacquire-native-server: + echo '$(AUGMENT_LIBRARY_PATH)' uno \ + -c com.sun.star.test.bridges.testacquire.impl \ + -l ../lib/$(SHL1TARGETN:f) -ro $(TARGET).rdb \ + -u $(TEST_JAVAUNO_ACQUIRE_UNO_URL) --singleaccept > $@ + $(GIVE_EXEC_RIGHTS) $@ diff --git a/bridges/test/java_uno/acquire/readme.txt b/bridges/test/java_uno/acquire/readme.txt new file mode 100644 index 000000000000..40bdf645c295 --- /dev/null +++ b/bridges/test/java_uno/acquire/readme.txt @@ -0,0 +1,21 @@ +Test scenarios: + +> cd .../bridges/<outdir>/bin +> ./testacquire-java-server & +> sleep 3 # wait for server to accept connection +> ./testacquire-java-client + +> cd .../bridges/<outdir>/bin +> ./testacquire-java-server & +> sleep 3 # wait for server to accept connection +> ./testacquire-native-client + +> cd .../bridges/<outdir>/bin +> ./testacquire-native-server & +> sleep 3 # wait for server to accept connection +> ./testacquire-java-client + +> cd .../bridges/<outdir>/bin +> ./testacquire-native-server & +> sleep 3 # wait for server to accept connection +> ./testacquire-native-client diff --git a/bridges/test/java_uno/acquire/testacquire.cxx b/bridges/test/java_uno/acquire/testacquire.cxx new file mode 100644 index 000000000000..7cca9a8a5498 --- /dev/null +++ b/bridges/test/java_uno/acquire/testacquire.cxx @@ -0,0 +1,568 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "com/sun/star/bridge/UnoUrlResolver.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/Type.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/conditn.hxx" +#include "osl/interlck.h" +#include "rtl/string.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "test/javauno/acquire/XBase.hpp" +#include "test/javauno/acquire/XDerived.hpp" +#include "test/javauno/acquire/XTest.hpp" +#include "uno/environment.h" +#include "uno/lbnames.h" + +#include <iostream> +#include <cstdlib> + +namespace css = com::sun::star; + +namespace { + +class WaitCondition { +public: + WaitCondition() {} + + ~WaitCondition(); + + osl::Condition & get() { return m_condition; } + +private: + WaitCondition(WaitCondition &); // not implemented + void operator =(WaitCondition); // not implemented + + osl::Condition m_condition; +}; + +} + +WaitCondition::~WaitCondition() { + std::cout << "waiting for condition\n"; + if (m_condition.wait() != osl::Condition::result_ok) { + std::cerr << "osl::Condition::wait failed\n"; + std::abort() + } +} + +namespace { + +class Interface: public css::uno::XInterface { +public: + explicit Interface(osl::Condition & condition): + m_condition(condition), m_refCount(0) {} + + virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL acquire() throw () + { osl_incrementInterlockedCount(&m_refCount); } + + virtual void SAL_CALL release() throw (); + +protected: + virtual ~Interface() { m_condition.set(); } + +private: + Interface(Interface &); // not implemented + void operator =(Interface); // not implemented + + osl::Condition & m_condition; + oslInterlockedCount m_refCount; +}; + +} + +css::uno::Any Interface::queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException) +{ + return type.getTypeName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.uno.XInterface")) + ? css::uno::makeAny(css::uno::Reference< css::uno::XInterface >(this)) + : css::uno::Any(); +} + +void Interface::release() throw () { + if (osl_decrementInterlockedCount(&m_refCount) == 0) { + delete this; + } +} + +namespace { + +class Base: public Interface, public test::javauno::acquire::XBase { +public: + explicit Base(osl::Condition & condition): Interface(condition) {} + + virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL acquire() throw () { Interface::acquire(); } + + virtual void SAL_CALL release() throw () { Interface::release(); } + +protected: + virtual ~Base() {} +}; + +} + +css::uno::Any Base::queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException) +{ + return type.getTypeName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "test.javauno.acquire.XBase")) + ? css::uno::makeAny( + css::uno::Reference< test::javauno::acquire::XBase >(this)) + : Interface::queryInterface(type); +} + +namespace { + +class Derived: public Base, public test::javauno::acquire::XDerived { +public: + explicit Derived(osl::Condition & condition): Base(condition) {} + + virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL acquire() throw () { Base::acquire(); } + + virtual void SAL_CALL release() throw () { Base::release(); } + +private: + virtual ~Derived() {} +}; + +} + +css::uno::Any Derived::queryInterface(css::uno::Type const & type) + throw (css::uno::RuntimeException) +{ + return (type.getTypeName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("test.javauno.acquire.XDerived"))) + ? css::uno::makeAny( + css::uno::Reference< test::javauno::acquire::XDerived >(this)) + : Interface::queryInterface(type); +} + +namespace { + +class Service: public cppu::WeakImplHelper3< + css::lang::XServiceInfo, css::lang::XMain, test::javauno::acquire::XTest > +{ +public: + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return getImplementationName_static(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return getSupportedServiceNames_static(); } + + virtual sal_Int32 SAL_CALL + run(css::uno::Sequence< rtl::OUString > const & arguments) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setInterfaceToInterface( + css::uno::Reference< css::uno::XInterface > const & obj) + throw (css::uno::RuntimeException) + { m_interface = obj; } + + virtual void SAL_CALL setBaseToInterface( + css::uno::Reference< test::javauno::acquire::XBase > const & obj) + throw (css::uno::RuntimeException) + { m_interface = obj; } + + virtual void SAL_CALL setDerivedToInterface( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { m_interface = obj; } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL getInterfaceFromInterface() throw (css::uno::RuntimeException) + { return m_interface; } + + virtual void SAL_CALL clearInterface() throw (css::uno::RuntimeException) + { m_interface.clear(); } + + virtual void SAL_CALL setBaseToBase( + css::uno::Reference< test::javauno::acquire::XBase > const & obj) + throw (css::uno::RuntimeException) + { m_base = obj; } + + virtual void SAL_CALL setDerivedToBase( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { m_base = obj.get(); } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL getInterfaceFromBase() throw (css::uno::RuntimeException) + { return m_base; } + + virtual css::uno::Reference< test::javauno::acquire::XBase > + SAL_CALL getBaseFromBase() throw (css::uno::RuntimeException) + { return m_base; } + + virtual void SAL_CALL clearBase() throw (css::uno::RuntimeException) + { m_base.clear(); } + + virtual void SAL_CALL setDerivedToDerived( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { m_derived = obj; } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL getInterfaceFromDerived() throw (css::uno::RuntimeException) + { return m_derived; } + + virtual css::uno::Reference< test::javauno::acquire::XBase > + SAL_CALL getBaseFromDerived() throw (css::uno::RuntimeException) + { return m_derived.get(); } + + virtual css::uno::Reference< test::javauno::acquire::XDerived > + SAL_CALL getDerivedFromDerived() throw (css::uno::RuntimeException) + { return m_derived; } + + virtual void SAL_CALL clearDerived() throw (css::uno::RuntimeException) + { m_derived.clear(); } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL roundTripInterfaceToInterface( + css::uno::Reference< css::uno::XInterface > const & obj) + throw (css::uno::RuntimeException) + { return obj; } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL roundTripBaseToInterface( + css::uno::Reference< test::javauno::acquire::XBase > const & obj) + throw (css::uno::RuntimeException) + { return obj; } + + virtual css::uno::Reference< css::uno::XInterface > + SAL_CALL roundTripDerivedToInterface( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { return obj; } + + virtual css::uno::Reference< test::javauno::acquire::XBase > + SAL_CALL roundTripBaseToBase( + css::uno::Reference< test::javauno::acquire::XBase > const & obj) + throw (css::uno::RuntimeException) + { return obj; } + + virtual css::uno::Reference< test::javauno::acquire::XBase > + SAL_CALL roundTripDerivedToBase( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { return obj.get(); } + + virtual css::uno::Reference< test::javauno::acquire::XDerived > + SAL_CALL roundTripDerivedToDerived( + css::uno::Reference< test::javauno::acquire::XDerived > const & obj) + throw (css::uno::RuntimeException) + { return obj; } + + static rtl::OUString getImplementationName_static(); + + static css::uno::Sequence< rtl::OUString > + getSupportedServiceNames_static(); + + static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception); + +private: + explicit Service( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) {} + + css::uno::Reference< css::uno::XComponentContext > m_context; + css::uno::Reference< css::uno::XInterface > m_interface; + css::uno::Reference< test::javauno::acquire::XBase > m_base; + css::uno::Reference< test::javauno::acquire::XDerived > m_derived; +}; + +} + +sal_Bool Service::supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< rtl::OUString > names( + getSupportedServiceNames_static()); + for (sal_Int32 i = 0; i< names.getLength(); ++i) { + if (names[i] == serviceName) { + return true; + } + } + return false; +} + +namespace { + +template< typename T > void assertNotNull(css::uno::Reference< T > const & ref) +{ + if (!ref.is()) { + std::cerr << "assertNotNull failed\n"; + std::abort(); + } +} + +} + +sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const & arguments) + throw (css::uno::RuntimeException) +{ + // - arguments[0] must be the UNO URL to connect to: + css::uno::Reference< XTest > test( + css::bridge::UnoUrlResolver::create(m_context)->resolve(arguments[0]), + css::uno::UNO_QUERY_THROW); + + { + WaitCondition c; + test->setInterfaceToInterface(new Interface(c.get())); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + { + WaitCondition c; + test->setInterfaceToInterface( + static_cast< Interface * >(new Base(c.get()))); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + { + WaitCondition c; + test->setInterfaceToInterface( + static_cast< Interface * >(new Derived(c.get()))); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + + { + WaitCondition c; + test->setBaseToInterface(new Base(c.get())); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + { + WaitCondition c; + test->setBaseToInterface(static_cast< Base * >(new Derived(c.get()))); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + + { + WaitCondition c; + test->setDerivedToInterface(new Derived(c.get())); + assertNotNull(test->getInterfaceFromInterface()); + test->clearInterface(); + } + + { + WaitCondition c; + test->setBaseToBase(new Base(c.get())); + assertNotNull(test->getInterfaceFromBase()); + assertNotNull(test->getBaseFromBase()); + test->clearBase(); + } + { + WaitCondition c; + test->setBaseToBase(static_cast< Base * >(new Derived(c.get()))); + assertNotNull(test->getInterfaceFromBase()); + assertNotNull(test->getBaseFromBase()); + test->clearBase(); + } + + { + WaitCondition c; + test->setDerivedToBase(new Derived(c.get())); + assertNotNull(test->getInterfaceFromBase()); + assertNotNull(test->getBaseFromBase()); + test->clearBase(); + } + + { + WaitCondition c; + test->setDerivedToDerived(new Derived(c.get())); + assertNotNull(test->getInterfaceFromDerived()); + assertNotNull(test->getBaseFromDerived()); + assertNotNull(test->getDerivedFromDerived()); + test->clearDerived(); + } + + { + WaitCondition c; + assertNotNull( + test->roundTripInterfaceToInterface(new Interface(c.get()))); + } + { + WaitCondition c; + assertNotNull(test->roundTripInterfaceToInterface( + static_cast< Interface * >(new Base(c.get())))); + } + { + WaitCondition c; + assertNotNull(test->roundTripInterfaceToInterface( + static_cast< Interface * >(new Derived(c.get())))); + } + + { + WaitCondition c; + assertNotNull(test->roundTripBaseToInterface(new Base(c.get()))); + } + { + WaitCondition c; + assertNotNull(test->roundTripBaseToInterface( + static_cast< Base * >(new Derived(c.get())))); + } + + { + WaitCondition c; + assertNotNull(test->roundTripDerivedToInterface(new Derived(c.get()))); + } + + { + WaitCondition c; + assertNotNull(test->roundTripBaseToBase(new Base(c.get()))); + } + { + WaitCondition c; + assertNotNull(test->roundTripBaseToBase( + static_cast< Base * >(new Derived(c.get())))); + } + + { + WaitCondition c; + assertNotNull(test->roundTripDerivedToBase(new Derived(c.get()))); + } + + { + WaitCondition c; + assertNotNull(test->roundTripDerivedToDerived(new Derived(c.get()))); + } + + std::cout << "Client and server both cleanly terminate now: Success\n"; + return 0; +} + +rtl::OUString Service::getImplementationName_static() { + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.test.bridges.testacquire.impl" )); +} + +css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames_static() { + css::uno::Sequence< rtl::OUString > names(1); + names[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.test.bridges.testacquire" )); + return names; +} + +css::uno::Reference< css::uno::XInterface > Service::createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(char const * implName, + void * serviceManager, void *) { + void * p = 0; + if (serviceManager != 0) { + css::uno::Reference< css::lang::XSingleComponentFactory > f; + if (Service::getImplementationName_static().equalsAscii(implName)) { + f = cppu::createSingleComponentFactory( + &Service::createInstance, + Service::getImplementationName_static(), + Service::getSupportedServiceNames_static()); + } + if (f.is()) { + f->acquire(); + p = f.get(); + } + } + return p; +} + +namespace { + +bool writeInfo(void * registryKey, rtl::OUString const & implementationName, + css::uno::Sequence< rtl::OUString > const & serviceNames) { + rtl::OUString keyName( RTL_CONSTASCII_USTRINGPARAM( "/" )); + keyName += implementationName; + keyName += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES" )); + css::uno::Reference< css::registry::XRegistryKey > key; + try { + key = static_cast< css::registry::XRegistryKey * >(registryKey)-> + createKey(keyName); + } catch (css::registry::InvalidRegistryException &) {} + if (!key.is()) { + return false; + } + bool success = true; + for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + try { + key->createKey(serviceNames[i]); + } catch (css::registry::InvalidRegistryException &) { + success = false; + break; + } + } + return success; +} + +} + +extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) { + return registryKey + && writeInfo(registryKey, Service::getImplementationName_static(), + Service::getSupportedServiceNames_static()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/java_uno/acquire/types.idl b/bridges/test/java_uno/acquire/types.idl new file mode 100644 index 000000000000..6dd2964777bd --- /dev/null +++ b/bridges/test/java_uno/acquire/types.idl @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "com/sun/star/uno/XInterface.idl" + +module test { module javauno { module acquire { + +interface XBase: com::sun::star::uno::XInterface {}; + +interface XDerived: XBase {}; + +interface XTest: com::sun::star::uno::XInterface +{ + void setInterfaceToInterface([in] com::sun::star::uno::XInterface obj); + void setBaseToInterface([in] XBase obj); + void setDerivedToInterface([in] XDerived obj); + com::sun::star::uno::XInterface getInterfaceFromInterface(); + void clearInterface(); + + void setBaseToBase([in] XBase obj); + void setDerivedToBase([in] XDerived obj); + com::sun::star::uno::XInterface getInterfaceFromBase(); + XBase getBaseFromBase(); + void clearBase(); + + void setDerivedToDerived([in] XDerived obj); + com::sun::star::uno::XInterface getInterfaceFromDerived(); + XBase getBaseFromDerived(); + XDerived getDerivedFromDerived(); + void clearDerived(); + + com::sun::star::uno::XInterface roundTripInterfaceToInterface( + [in] com::sun::star::uno::XInterface obj); + com::sun::star::uno::XInterface roundTripBaseToInterface([in] XBase obj); + com::sun::star::uno::XInterface roundTripDerivedToInterface( + [in] XDerived obj); + + XBase roundTripBaseToBase([in] XBase obj); + XBase roundTripDerivedToBase([in] XDerived obj); + + XDerived roundTripDerivedToDerived([in] XDerived obj); +}; + +}; }; }; diff --git a/bridges/test/java_uno/any/TestAny.java b/bridges/test/java_uno/any/TestAny.java new file mode 100644 index 000000000000..43e8bf542479 --- /dev/null +++ b/bridges/test/java_uno/any/TestAny.java @@ -0,0 +1,2267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.java_uno.anytest; + +import com.sun.star.uno.Any; +import com.sun.star.uno.Enum; +import com.sun.star.uno.Type; +import com.sun.star.uno.TypeClass; +import com.sun.star.uno.XInterface; +import java.lang.reflect.Array; + +final class TestAny { + public static boolean test(XTransport transport, boolean createTypes) { + boolean success = true; + + // Sanity check for com.sun.star.uno.Type: + success &= testType(void.class, TypeClass.VOID, "void"); + success &= testType(boolean.class, TypeClass.BOOLEAN, "boolean"); + success &= testType(byte.class, TypeClass.BYTE, "byte"); + success &= testType(short.class, TypeClass.SHORT, "short"); + success &= testType(int.class, TypeClass.LONG, "long"); + success &= testType(long.class, TypeClass.HYPER, "hyper"); + success &= testType(float.class, TypeClass.FLOAT, "float"); + success &= testType(double.class, TypeClass.DOUBLE, "double"); + success &= testType(char.class, TypeClass.CHAR, "char"); + success &= testType(String.class, TypeClass.STRING, "string"); + success &= testType(Type.class, TypeClass.TYPE, "type"); + success &= testType(Any.class, TypeClass.ANY, "any"); + success &= testType(boolean[].class, TypeClass.SEQUENCE, "[]boolean"); + success &= testType(byte[].class, TypeClass.SEQUENCE, "[]byte"); + success &= testType(short[].class, TypeClass.SEQUENCE, "[]short"); + success &= testType(int[].class, TypeClass.SEQUENCE, "[]long"); + success &= testType(long[].class, TypeClass.SEQUENCE, "[]hyper"); + success &= testType(float[].class, TypeClass.SEQUENCE, "[]float"); + success &= testType(double[].class, TypeClass.SEQUENCE, "[]double"); + success &= testType(char[].class, TypeClass.SEQUENCE, "[]char"); + success &= testType(String[].class, TypeClass.SEQUENCE, "[]string"); + success &= testType(Type[].class, TypeClass.SEQUENCE, "[]type"); + success &= testType(Any[].class, TypeClass.SEQUENCE, "[]any"); + success &= testType(Enum1[].class, TypeClass.SEQUENCE, + "[]" + Enum1.class.getName()); + success &= testType(BaseStruct[].class, TypeClass.SEQUENCE, + "[]" + BaseStruct.class.getName()); + success &= testType(DerivedStruct[].class, TypeClass.SEQUENCE, + "[]" + DerivedStruct.class.getName()); + success &= testType(XInterface[].class, TypeClass.SEQUENCE, + "[]" + XInterface.class.getName()); + success &= testType(BaseInterface[].class, TypeClass.SEQUENCE, + "[]" + BaseInterface.class.getName()); + success &= testType(DerivedInterface[].class, TypeClass.SEQUENCE, + "[]" + DerivedInterface.class.getName()); + success &= testType(boolean[][].class, TypeClass.SEQUENCE, + "[][]boolean"); + success &= testType(byte[][].class, TypeClass.SEQUENCE, "[][]byte"); + success &= testType(short[][].class, TypeClass.SEQUENCE, "[][]short"); + success &= testType(int[][].class, TypeClass.SEQUENCE, "[][]long"); + success &= testType(long[][].class, TypeClass.SEQUENCE, "[][]hyper"); + success &= testType(float[][].class, TypeClass.SEQUENCE, "[][]float"); + success &= testType(double[][].class, TypeClass.SEQUENCE, "[][]double"); + success &= testType(char[][].class, TypeClass.SEQUENCE, "[][]char"); + success &= testType(String[][].class, TypeClass.SEQUENCE, "[][]string"); + success &= testType(Type[][].class, TypeClass.SEQUENCE, "[][]type"); + success &= testType(Any[][].class, TypeClass.SEQUENCE, "[][]any"); + success &= testType(Enum1[][].class, TypeClass.SEQUENCE, + "[][]" + Enum1.class.getName()); + success &= testType(BaseStruct[][].class, TypeClass.SEQUENCE, + "[][]" + BaseStruct.class.getName()); + success &= testType(DerivedStruct[][].class, TypeClass.SEQUENCE, + "[][]" + DerivedStruct.class.getName()); + success &= testType(XInterface[][].class, TypeClass.SEQUENCE, + "[][]" + XInterface.class.getName()); + success &= testType(BaseInterface[][].class, TypeClass.SEQUENCE, + "[][]" + BaseInterface.class.getName()); + success &= testType(DerivedInterface[][].class, TypeClass.SEQUENCE, + "[][]" + DerivedInterface.class.getName()); + success &= testType(Enum1.class, TypeClass.ENUM, Enum1.class.getName()); + success &= testType(BaseStruct.class, TypeClass.STRUCT, + BaseStruct.class.getName()); + success &= testType(DerivedStruct.class, TypeClass.STRUCT, + DerivedStruct.class.getName()); + success &= testType(com.sun.star.uno.Exception.class, + TypeClass.EXCEPTION, + com.sun.star.uno.Exception.class.getName()); + success &= testType(com.sun.star.uno.RuntimeException.class, + TypeClass.EXCEPTION, + com.sun.star.uno.RuntimeException.class.getName()); + success &= testType(XInterface.class, TypeClass.INTERFACE, + XInterface.class.getName()); + success &= testType(BaseInterface.class, TypeClass.INTERFACE, + BaseInterface.class.getName()); + success &= testType(DerivedInterface.class, TypeClass.INTERFACE, + DerivedInterface.class.getName()); + + // VOID: + success &= testMapAny(transport, Any.VOID, new CompareBoxed()); + + // BOOLEAN: + success &= testMapAny(transport, Boolean.FALSE, new CompareBoxed()); + success &= testMapAny(transport, Boolean.TRUE, new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.BOOLEAN, Boolean.FALSE), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.BOOLEAN, Boolean.TRUE), + new CompareUnboxed()); + + // BYTE: + success &= testMapAny(transport, new Byte((byte) -128), + new CompareBoxed()); + success &= testMapAny(transport, new Byte((byte) 0), + new CompareBoxed()); + success &= testMapAny(transport, new Byte((byte) 127), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.BYTE, new Byte((byte) -128)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.BYTE, new Byte((byte) 0)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.BYTE, new Byte((byte) 127)), + new CompareUnboxed()); + + // SHORT: + success &= testMapAny(transport, new Short((short) -32768), + new CompareBoxed()); + success &= testMapAny(transport, new Short((short) 0), + new CompareBoxed()); + success &= testMapAny(transport, new Short((short) 32767), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.SHORT, + new Short((short) -32768)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.SHORT, new Short((short) 0)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.SHORT, new Short((short) 32767)), + new CompareUnboxed()); + + // UNSIGNED SHORT: + success &= testMapAny(transport, + new Any(Type.UNSIGNED_SHORT, + new Short((short) 0)), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.UNSIGNED_SHORT, + new Short((short) -32768)), + new CompareBoxed()); + + // LONG: + success &= testMapAny(transport, new Integer(-2147483648), + new CompareBoxed()); + success &= testMapAny(transport, new Integer(0), + new CompareBoxed()); + success &= testMapAny(transport, new Integer(2147483647), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.LONG, new Integer(-2147483648)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.LONG, new Integer(0)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.LONG, new Integer(2147483647)), + new CompareUnboxed()); + + // UNSIGNED LONG: + success &= testMapAny(transport, + new Any(Type.UNSIGNED_LONG, new Integer(0)), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.UNSIGNED_LONG, + new Integer(-2147483648)), + new CompareBoxed()); + + // HYPER: + success &= testMapAny(transport, new Long(-9223372036854775808L), + new CompareBoxed()); + success &= testMapAny(transport, new Long(0L), new CompareBoxed()); + success &= testMapAny(transport, new Long(9223372036854775807L), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.HYPER, + new Long(-9223372036854775808L)), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.HYPER, new Long(0L)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.HYPER, + new Long(9223372036854775807L)), + new CompareUnboxed()); + + // UNSIGNED HYPER: + success &= testMapAny(transport, + new Any(Type.UNSIGNED_HYPER, new Long(0L)), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.UNSIGNED_HYPER, + new Long(-9223372036854775808L)), + new CompareBoxed()); + + // FLOAT: + success &= testMapAny(transport, new Float(Float.NEGATIVE_INFINITY), + new CompareBoxed()); + success &= testMapAny(transport, new Float(Float.MIN_VALUE), + new CompareBoxed()); + success &= testMapAny(transport, new Float(-0.0f), + new CompareBoxed()); + success &= testMapAny(transport, new Float(0.0f), + new CompareBoxed()); + success &= testMapAny(transport, new Float(Float.MAX_VALUE), + new CompareBoxed()); + success &= testMapAny(transport, new Float(Float.POSITIVE_INFINITY), + new CompareBoxed()); + success &= testMapAny(transport, new Float(Float.NaN), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, + new Float(Float.NEGATIVE_INFINITY)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, + new Float(Float.MIN_VALUE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, new Float(-0.0f)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, new Float(0.0f)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, + new Float(Float.MAX_VALUE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, + new Float(Float.POSITIVE_INFINITY)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.FLOAT, new Float(Float.NaN)), + new CompareUnboxed()); + + // DOUBLE: + success &= testMapAny(transport, + new Double(Double.NEGATIVE_INFINITY), + new CompareBoxed()); + success &= testMapAny(transport, new Double(Double.MIN_VALUE), + new CompareBoxed()); + success &= testMapAny(transport, new Double(-0.0f), + new CompareBoxed()); + success &= testMapAny(transport, new Double(0.0f), + new CompareBoxed()); + success &= testMapAny(transport, new Double(Double.MAX_VALUE), + new CompareBoxed()); + success &= testMapAny(transport, + new Double(Double.POSITIVE_INFINITY), + new CompareBoxed()); + success &= testMapAny(transport, new Double(Double.NaN), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, + new Double(Double.NEGATIVE_INFINITY)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, + new Double(Double.MIN_VALUE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, new Double(-0.0)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, new Double(0.0)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, + new Double(Double.MAX_VALUE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, + new Double(Double.POSITIVE_INFINITY)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.DOUBLE, new Double(Double.NaN)), + new CompareUnboxed()); + + // CHAR: + success &= testMapAny(transport, new Character('\u0000'), + new CompareBoxed()); + success &= testMapAny(transport, new Character('\uDBFF'), + new CompareBoxed()); + success &= testMapAny(transport, new Character('\uFFFD'), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(Type.CHAR, new Character('\u0000')), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.CHAR, new Character('\uDBFF')), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.CHAR, new Character('\uFFFD')), + new CompareUnboxed()); + + // STRING: + success &= testMapAny(transport, "", new CompareBoxed()); + success &= testMapAny(transport, "\uD800\uDC00", + new CompareBoxed()); + success &= testMapAny(transport, "Test", new CompareBoxed()); + success &= testMapAny(transport, new Any(Type.STRING, ""), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.STRING, "\uD800\uDC00"), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.STRING, "Test"), + new CompareUnboxed()); + + // TYPE: + success &= testMapAny(transport, Type.VOID, new CompareBoxed()); + success &= testMapAny(transport, Type.BOOLEAN, new CompareBoxed()); + success &= testMapAny(transport, Type.BYTE, new CompareBoxed()); + success &= testMapAny(transport, Type.SHORT, new CompareBoxed()); + success &= testMapAny(transport, Type.UNSIGNED_SHORT, + new CompareBoxed()); + success &= testMapAny(transport, Type.LONG, new CompareBoxed()); + success &= testMapAny(transport, Type.UNSIGNED_LONG, + new CompareBoxed()); + success &= testMapAny(transport, Type.HYPER, new CompareBoxed()); + success &= testMapAny(transport, Type.UNSIGNED_HYPER, + new CompareBoxed()); + success &= testMapAny(transport, Type.FLOAT, new CompareBoxed()); + success &= testMapAny(transport, Type.DOUBLE, new CompareBoxed()); + success &= testMapAny(transport, Type.CHAR, new CompareBoxed()); + success &= testMapAny(transport, Type.STRING, new CompareBoxed()); + success &= testMapAny(transport, Type.TYPE, new CompareBoxed()); + success &= testMapAny(transport, Type.ANY, new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]boolean", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]byte", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]short", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]unsigned short", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]long", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]unsigned long", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]hyper", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]unsigned hyper", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]float", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]double", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]char", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]string", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]type", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]any", TypeClass.SEQUENCE), + new CompareBoxed()); + if (createTypes) { + success &= testMapAny(transport, + new Type("[]" + Enum1.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]" + BaseStruct.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]" + DerivedStruct.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + } + success &= testMapAny(transport, + new Type("[]" + XInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]" + BaseInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[]" + + DerivedInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]boolean", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]byte", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]short", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]unsigned short", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]long", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]unsigned long", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]hyper", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]unsigned hyper", + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]float", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]double", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]char", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]string", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]type", TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]any", TypeClass.SEQUENCE), + new CompareBoxed()); + if (createTypes) { + success &= testMapAny(transport, + new Type("[][]" + Enum1.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]" + BaseStruct.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]" + + DerivedStruct.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + } + success &= testMapAny(transport, + new Type("[][]" + XInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]" + + BaseInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type("[][]" + + DerivedInterface.class.getName(), + TypeClass.SEQUENCE), + new CompareBoxed()); + if (createTypes) { + success &= testMapAny(transport, new Type(Enum1.class.getName(), + TypeClass.ENUM), + new CompareBoxed()); + success &= testMapAny(transport, + new Type(BaseStruct.class.getName(), + TypeClass.STRUCT), + new CompareBoxed()); + success &= testMapAny(transport, + new Type(DerivedStruct.class.getName(), + TypeClass.STRUCT), + new CompareBoxed()); + } + success &= testMapAny(transport, + new Type( + com.sun.star.uno.Exception.class. + getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + if (createTypes) { + success &= testMapAny(transport, + new Type(BaseException.class.getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + success &= testMapAny(transport, + new Type(DerivedException.class.getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + } + success &= testMapAny(transport, + new Type( + com.sun.star.uno.RuntimeException.class. + getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + if (createTypes) { + success &= testMapAny(transport, + new Type( + BaseRuntimeException.class.getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + success &= testMapAny(transport, + new Type( + DerivedRuntimeException.class. + getName(), + TypeClass.EXCEPTION), + new CompareBoxed()); + } + success &= testMapAny(transport, + new Type(XInterface.class.getName(), + TypeClass.INTERFACE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type(BaseInterface.class.getName(), + TypeClass.INTERFACE), + new CompareBoxed()); + success &= testMapAny(transport, + new Type(DerivedInterface.class.getName(), + TypeClass.INTERFACE), + new CompareBoxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.VOID), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.BOOLEAN), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.BYTE), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.SHORT), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, Type.UNSIGNED_SHORT), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.LONG), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, Type.UNSIGNED_LONG), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.HYPER), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, Type.UNSIGNED_HYPER), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.FLOAT), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.DOUBLE), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.CHAR), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.STRING), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.TYPE), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(Type.TYPE, Type.ANY), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]boolean", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]byte", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]short", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]unsigned short", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]long", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]unsigned long", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]hyper", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]unsigned hyper", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]float", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]double", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]char", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]string", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]type", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]any", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + if (createTypes) { + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]" + Enum1.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]" + + BaseStruct.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + "[]" + + DerivedStruct.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[]" + + XInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + "[]" + + BaseInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + "[]" + + DerivedInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]boolean", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]byte", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]short", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]unsigned short", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]long", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]unsigned long", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]hyper", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]unsigned hyper", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]float", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]double", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]char", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]string", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]type", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]any", + TypeClass.SEQUENCE)), + new CompareUnboxed()); + if (createTypes) { + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]" + + Enum1.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]" + + BaseStruct.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + "[][]" + + DerivedStruct.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type("[][]" + + XInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + "[][]" + + BaseInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + "[][]" + + DerivedInterface.class.getName(), + TypeClass.SEQUENCE)), + new CompareUnboxed()); + if (createTypes) { + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type(Enum1.class.getName(), + TypeClass.ENUM)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type(BaseStruct.class.getName(), + TypeClass.STRUCT)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + DerivedStruct.class.getName(), + TypeClass.STRUCT)), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + com.sun.star.uno.Exception.class. + getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + if (createTypes) { + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + BaseException.class.getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + DerivedException.class.getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + com.sun.star.uno.RuntimeException. + class.getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + if (createTypes) { + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + BaseRuntimeException.class. + getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + Type.TYPE, + new Type( + DerivedRuntimeException.class. + getName(), + TypeClass.EXCEPTION)), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type(XInterface.class.getName(), + TypeClass.INTERFACE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + BaseInterface.class.getName(), + TypeClass.INTERFACE)), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(Type.TYPE, + new Type( + DerivedInterface.class.getName(), + TypeClass.INTERFACE)), + new CompareUnboxed()); + + // Sequence Types: + success &= testMapAny(transport, new boolean[] {}, + new CompareBoxed()); + success &= testMapAny(transport, new boolean[] { false, true }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(boolean[].class), + new boolean[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(boolean[].class), + new boolean[] { false, true }), + new CompareUnboxed()); + success &= testMapAny(transport, new byte[] {}, + new CompareBoxed()); + success &= testMapAny(transport, new byte[] { -128, 0, 127 }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(byte[].class), + new byte[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(byte[].class), + new byte[] { -128, 0, 127 }), + new CompareUnboxed()); + success &= testMapAny(transport, new short[] {}, + new CompareBoxed()); + success &= testMapAny(transport, new short[] { -32768, 0, 32767 }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(short[].class), + new short[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(short[].class), + new short[] { -32768, 0, 32767 }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned short", + TypeClass.SEQUENCE), + new short[] {}), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned short", + TypeClass.SEQUENCE), + new short[] { 0, -32768 }), + new CompareBoxed()); + success &= testMapAny(transport, new int[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new int[] { -2147483648, 0, 2147483647 }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(int[].class), + new int[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(int[].class), + new int[] { -2147483648, 0, + 2147483647 }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned long", + TypeClass.SEQUENCE), + new int[] {}), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned long", + TypeClass.SEQUENCE), + new int[] { 0, -2147483648 }), + new CompareBoxed()); + success &= testMapAny(transport, new long[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new long[] { -9223372036854775808L, 0L, + 9223372036854775807L }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(long[].class), + new long[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(long[].class), + new long[] { -9223372036854775808L, + 0L, + 9223372036854775807L }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned hyper", + TypeClass.SEQUENCE), + new long[] {}), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[]unsigned hyper", + TypeClass.SEQUENCE), + new long[] { 0L, + -9223372036854775808L }), + new CompareBoxed()); + success &= testMapAny(transport, new float[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new float[] { Float.NEGATIVE_INFINITY, + Float.MIN_VALUE, -0.0f, 0.0f, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY, + Float.NaN }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(float[].class), + new float[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(float[].class), + new float[] { Float.NEGATIVE_INFINITY, + Float.MIN_VALUE, -0.0f, + 0.0f, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, + Float.NaN }), + new CompareUnboxed()); + success &= testMapAny(transport, new double[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new double[] { Double.NEGATIVE_INFINITY, + Double.MIN_VALUE, -0.0, 0.0, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(double[].class), + new double[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(double[].class), + new double[] { + Double.NEGATIVE_INFINITY, + Double.MIN_VALUE, -0.0, 0.0, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN }), + new CompareUnboxed()); + success &= testMapAny(transport, new char[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new char[] { '\u0000', '\uDBFF', '\uFFFD' }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(char[].class), + new char[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(char[].class), + new char[] { '\u0000', '\uDBFF', + '\uFFFD' }), + new CompareUnboxed()); + success &= testMapAny(transport, new String[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new String[] { "", "\uD800\uDC00", "Test" }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(String[].class), + new String[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(String[].class), + new String[] { "", "\uD800\uDC00", + "Test" }), + new CompareUnboxed()); + success &= testMapAny(transport, new Type[] {}, new CompareBoxed()); + success &= testMapAny(transport, + new Type[] { + Type.VOID, + new Type(DerivedInterface.class.getName(), + TypeClass.INTERFACE) }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(Type[].class), + new Type[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(Type[].class), + new Type[] { + Type.VOID, + new Type( + DerivedInterface.class.getName(), + TypeClass.INTERFACE) }), + new CompareUnboxed()); + success &= testMapAny(transport, new Object[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new Object[] { Any.VOID, Boolean.FALSE }, + new CompareBoxed()); + success &= testMapAny(transport, + new Object[] { + Boolean.FALSE, + new Any(Type.BOOLEAN, Boolean.TRUE) }, + new CompareBoxed(true)); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Object[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Object[] { Any.VOID, + Boolean.FALSE }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Object[] { + Boolean.FALSE, + new Any(Type.BOOLEAN, + Boolean.TRUE) }), + new CompareUnboxed(true)); + success &= testMapAny(transport, new Any[] {}, + new CompareSpecific(new Object[] {})); + success &= testMapAny(transport, + new Any[] { Any.VOID, + new Any(Type.BOOLEAN, + Boolean.TRUE) }, + new CompareSpecific( + new Object[] { Any.VOID, Boolean.TRUE })); + success &= testMapAny(transport, + new Any(new Type(Any[].class), new Any[] {}), + new CompareSpecific(new Object[] {})); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Any[] { Any.VOID, + new Any(Type.BOOLEAN, + Boolean.TRUE) }), + new CompareSpecific( + new Object[] { Any.VOID, Boolean.TRUE })); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Boolean[] {}), + new CompareSpecific(new Object[] {})); + success &= testMapAny(transport, + new Any(new Type(Any[].class), + new Boolean[] { Boolean.FALSE }), + new CompareSpecific( + new Object[] { Boolean.FALSE })); + if (createTypes) { + success &= testMapAny(transport, new Enum1[] {}, + new CompareBoxed()); + success &= testMapAny(transport, new Enum1[] { new Enum1(), + new Enum2() }, + new CompareSpecific( + new Enum1[] { new Enum1(), + new Enum1() })); + success &= testMapAny(transport, + new Any(new Type(Enum1[].class), + new Enum1[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Enum1[].class), + new Enum1[] { new Enum1(), + new Enum2() }), + new CompareSpecific( + new Enum1[] { new Enum1(), + new Enum1() })); + success &= testMapAny(transport, + new Any(new Type(Enum1[].class), + new Enum2[] {}), + new CompareSpecific(new Enum1[] {})); + success &= testMapAny(transport, + new Any(new Type(Enum1[].class), + new Enum2[] { new Enum2() }), + new CompareSpecific( + new Enum1[] { new Enum1() })); + success &= testMapAny(transport, new BaseStruct[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new BaseStruct[] { new BaseStruct(), + new DerivedStruct() }, + new CompareSpecific( + new BaseStruct[] { new BaseStruct(), + new BaseStruct() })); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[].class), + new BaseStruct[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[].class), + new BaseStruct[] { + new BaseStruct(), + new DerivedStruct() }), + new CompareSpecific( + new BaseStruct[] { new BaseStruct(), + new BaseStruct() })); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[].class), + new DerivedStruct[] {}), + new CompareSpecific(new BaseStruct[] {})); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[].class), + new DerivedStruct[] { + new DerivedStruct() }), + new CompareSpecific( + new BaseStruct[] { new BaseStruct() })); + success &= testMapAny(transport, new DerivedStruct[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new DerivedStruct[] { new DerivedStruct() }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedStruct[].class), + new DerivedStruct[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedStruct[].class), + new DerivedStruct[] { + new DerivedStruct() }), + new CompareUnboxed()); + } + success &= testMapAny(transport, new XInterface[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new XInterface[] { + null, new XInterface() {}, + new BaseInterface() {}, + new DerivedInterface() {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new XInterface[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new XInterface[] { + null, new XInterface() {}, + new BaseInterface() {}, + new DerivedInterface() {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new Object[] {}), + new CompareSpecific(new XInterface[] {})); + { + XInterface if1 = new XInterface() {}; + XInterface if2 = new BaseInterface() {}; + XInterface if3 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new Object[] { null, if1, if2, + if3 }), + new CompareSpecific( + new XInterface[] { null, if1, if2, + if3 })); + } + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new BaseInterface[] {}), + new CompareSpecific(new XInterface[] {})); + { + BaseInterface if1 = new BaseInterface() {}; + BaseInterface if2 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new BaseInterface[] { null, if1, + if2 }), + new CompareSpecific( + new XInterface[] { null, if1, if2 })); + } + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new DerivedInterface[] {}), + new CompareSpecific(new XInterface[] {})); + { + DerivedInterface if1 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[].class), + new DerivedInterface[] { null, + if1 }), + new CompareSpecific( + new XInterface[] { null, if1 })); + } + success &= testMapAny(transport, new BaseInterface[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new BaseInterface[] { + null, new BaseInterface() {}, + new DerivedInterface() {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface[].class), + new BaseInterface[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface[].class), + new BaseInterface[] { + null, new BaseInterface() {}, + new DerivedInterface() {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface[].class), + new DerivedInterface[] {}), + new CompareSpecific(new BaseInterface[] {})); + { + DerivedInterface if1 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(BaseInterface[].class), + new DerivedInterface[] { null, + if1 }), + new CompareSpecific( + new BaseInterface[] { null, if1 })); + } + success &= testMapAny(transport, new DerivedInterface[] {}, + new CompareBoxed()); + success &= testMapAny(transport, + new DerivedInterface[] { + null, new DerivedInterface() {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedInterface[].class), + new DerivedInterface[] {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedInterface[].class), + new DerivedInterface[] { + null, + new DerivedInterface() {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new boolean[][] { new boolean[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new boolean[][] { + new boolean[] { false, true } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(boolean[][].class), + new boolean[][] { new boolean[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(boolean[][].class), + new boolean[][] { + new boolean[] { false, true } }), + new CompareUnboxed()); + success &= testMapAny(transport, new byte[][] { new byte[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new byte[][] { new byte[] { -128, 0, 127 } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(byte[][].class), + new byte[][] { new byte[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(byte[][].class), + new byte[][] { + new byte[] { -128, 0, 127 } }), + new CompareUnboxed()); + success &= testMapAny(transport, new short[][] { new short[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new short[][] { + new short[] { -32768, 0, 32767 } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(short[][].class), + new short[][] { new short[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(short[][].class), + new short[][] { + new short[] { -32768, 0, + 32767 } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned short", + TypeClass.SEQUENCE), + new short[][] { new short[] {} }), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned short", + TypeClass.SEQUENCE), + new short[][] { + new short[] { 0, -32768 } }), + new CompareBoxed()); + success &= testMapAny(transport, new int[][] { new int[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new int[][] { new int[] { -2147483648, 0, + 2147483647 } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(int[][].class), + new int[][] { new int[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(int[][].class), + new int[][] { + new int[] { -2147483648, 0, + 2147483647 } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned long", + TypeClass.SEQUENCE), + new int[][] { new int[] {} }), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned long", + TypeClass.SEQUENCE), + new int[][] { + new int[] { 0, -2147483648 } }), + new CompareBoxed()); + success &= testMapAny(transport, new long[][] { new long[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new long[][] { + new long[] { -9223372036854775808L, 0L, + 9223372036854775807L } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(long[][].class), + new long[][] { new long[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(long[][].class), + new long[][] { + new long[] { + -9223372036854775808L, 0L, + 9223372036854775807L } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned hyper", + TypeClass.SEQUENCE), + new long[][] { new long[] {} }), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type("[][]unsigned hyper", + TypeClass.SEQUENCE), + new long[][] { + new long[] { + 0L, + -9223372036854775808L } }), + new CompareBoxed()); + success &= testMapAny(transport, new float[][] { new float[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new float[][] { + new float[] { Float.NEGATIVE_INFINITY, + Float.MIN_VALUE, -0.0f, + 0.0f, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, + Float.NaN } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(float[][].class), + new float[][] { new float[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(float[][].class), + new float[][] { + new float[] { + Float.NEGATIVE_INFINITY, + Float.MIN_VALUE, -0.0f, 0.0f, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY, + Float.NaN } }), + new CompareUnboxed()); + success &= testMapAny(transport, new double[][] { new double[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new double[][] { + new double[] { Double.NEGATIVE_INFINITY, + Double.MIN_VALUE, -0.0, + 0.0, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(double[][].class), + new double[][] { new double[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(double[][].class), + new double[][] { + new double[] { + Double.NEGATIVE_INFINITY, + Double.MIN_VALUE, -0.0, 0.0, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN } }), + new CompareUnboxed()); + success &= testMapAny(transport, new char[][] { new char[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new char[][] { + new char[] { '\u0000', '\uDBFF', + '\uFFFD' } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(char[][].class), + new char[][] { new char[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(char[][].class), + new char[][] { + new char[] { '\u0000', '\uDBFF', + '\uFFFD' } }), + new CompareUnboxed()); + success &= testMapAny(transport, new String[][] { new String[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new String[][] { + new String[] { "", "\uD800\uDC00", + "Test" } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(String[][].class), + new String[][] { new String[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(String[][].class), + new String[][] { + new String[] { "", "\uD800\uDC00", + "Test" } }), + new CompareUnboxed()); + success &= testMapAny(transport, new Type[][] { new Type[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Type[][] { + new Type[] { + Type.VOID, + new Type( + DerivedInterface.class.getName(), + TypeClass.INTERFACE) } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(Type[][].class), + new Type[][] { new Type[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(Type[][].class), + new Type[][] { + new Type[] { + Type.VOID, + new Type( + DerivedInterface.class. + getName(), + TypeClass.INTERFACE) } }), + new CompareUnboxed()); + success &= testMapAny(transport, new Object[][] { new Object[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Object[][] { + new Object[] { Any.VOID, + Boolean.FALSE } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Object[][] { + new Object[] { + Boolean.FALSE, + new Any(Type.BOOLEAN, + Boolean.TRUE) } }, + new CompareBoxed(true)); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Object[][] { new Object[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Object[][] { + new Object[] { Any.VOID, + Boolean.FALSE } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Object[][] { + new Object[] { + Boolean.FALSE, + new Any(Type.BOOLEAN, + Boolean.TRUE) } }), + new CompareUnboxed(true)); + success &= testMapAny(transport, new Any[][] { new Any[] {} }, + new CompareSpecific( + new Object[][] { new Object[] {} })); + success &= testMapAny(transport, + new Any[][] { + new Any[] { Any.VOID, + new Any(Type.BOOLEAN, + Boolean.TRUE) } }, + new CompareSpecific( + new Object[][] { + new Object[] { Any.VOID, + Boolean.TRUE } })); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Any[][] { new Any[] {} }), + new CompareSpecific( + new Object[][] { new Object[] {} })); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Any[][] { + new Any[] { + Any.VOID, + new Any(Type.BOOLEAN, + Boolean.TRUE) } }), + new CompareSpecific( + new Object[][] { + new Object[] { Any.VOID, + Boolean.TRUE } })); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Boolean[][] { new Boolean[] {} }), + new CompareSpecific( + new Object[][] { new Object[] {} })); + success &= testMapAny(transport, + new Any(new Type(Any[][].class), + new Boolean[][] { + new Boolean[] { + Boolean.FALSE } }), + new CompareSpecific( + new Object[][] { + new Object[] { Boolean.FALSE } })); + if (createTypes) { + success &= testMapAny(transport, new Enum1[][] { new Enum1[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new Enum1[][] { + new Enum1[] { new Enum1(), + new Enum2() } }, + new CompareSpecific( + new Enum1[][] { + new Enum1[] { new Enum1(), + new Enum1() } })); + success &= testMapAny(transport, + new Any(new Type(Enum1[][].class), + new Enum1[][] { new Enum1[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(Enum1[][].class), + new Enum1[][] { + new Enum1[] { new Enum1(), + new Enum2() } }), + new CompareSpecific( + new Enum1[][] { + new Enum1[] { new Enum1(), + new Enum1() } })); + success &= testMapAny(transport, + new Any(new Type(Enum1[][].class), + new Enum2[][] { new Enum2[] {} }), + new CompareSpecific( + new Enum1[][] { new Enum1[] {} })); + success &= testMapAny(transport, + new Any(new Type(Enum1[][].class), + new Enum2[][] { + new Enum2[] { new Enum2() } }), + new CompareSpecific( + new Enum1[][] { + new Enum1[] { new Enum1() } })); + success &= testMapAny(transport, + new BaseStruct[][] { new BaseStruct[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new BaseStruct[][] { + new BaseStruct[] { + new BaseStruct(), + new DerivedStruct() } }, + new CompareSpecific( + new BaseStruct[][] { + new BaseStruct[] { + new BaseStruct(), + new BaseStruct() } })); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[][].class), + new BaseStruct[][] { + new BaseStruct[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[][].class), + new BaseStruct[][] { + new BaseStruct[] { + new BaseStruct(), + new DerivedStruct() } }), + new CompareSpecific( + new BaseStruct[][] { + new BaseStruct[] { + new BaseStruct(), + new BaseStruct() } })); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[][].class), + new DerivedStruct[][] { + new DerivedStruct[] {} }), + new CompareSpecific( + new BaseStruct[][] { + new BaseStruct[] {} })); + success &= testMapAny(transport, + new Any(new Type(BaseStruct[][].class), + new DerivedStruct[][] { + new DerivedStruct[] { + new DerivedStruct() } }), + new CompareSpecific( + new BaseStruct[][] { + new BaseStruct[] { + new BaseStruct() } })); + success &= testMapAny(transport, + new DerivedStruct[][] { + new DerivedStruct[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new DerivedStruct[][] { + new DerivedStruct[] { + new DerivedStruct() } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedStruct[][].class), + new DerivedStruct[][] { + new DerivedStruct[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedStruct[][].class), + new DerivedStruct[][] { + new DerivedStruct[] { + new DerivedStruct() } }), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new XInterface[][] { new XInterface[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new XInterface[][] { + new XInterface[] { + null, new XInterface() {}, + new BaseInterface() {}, + new DerivedInterface() {} } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new XInterface[][] { + new XInterface[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(XInterface[][].class), + new XInterface[][] { + new XInterface[] { + null, new XInterface() {}, + new BaseInterface() {}, + new DerivedInterface() {} } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new Object[][] { new Object[] {} }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] {} })); + { + XInterface if1 = new XInterface() {}; + XInterface if2 = new BaseInterface() {}; + XInterface if3 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new Object[][] { + new Object[] { null, if1, if2, + if3 } }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] { null, if1, if2, + if3 } })); + } + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new BaseInterface[][] { + new BaseInterface[] {} }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] {} })); + { + BaseInterface if1 = new BaseInterface() {}; + BaseInterface if2 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new BaseInterface[][] { + new BaseInterface[] { + null, if1, if2 } }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] { + null, if1, if2 } })); + } + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] {} }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] {} })); + { + DerivedInterface if1 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(XInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] { + null, if1 } }), + new CompareSpecific( + new XInterface[][] { + new XInterface[] { + null, if1 } })); + } + success &= testMapAny(transport, + new BaseInterface[][] { + new BaseInterface[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new BaseInterface[][] { + new BaseInterface[] { + null, new BaseInterface() {}, + new DerivedInterface() {} } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface[][].class), + new BaseInterface[][] { + new BaseInterface[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(BaseInterface[][].class), + new BaseInterface[][] { + new BaseInterface[] { + null, new BaseInterface() {}, + new DerivedInterface() {} } }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] {} }), + new CompareSpecific( + new BaseInterface[][] { + new BaseInterface[] {} })); + { + DerivedInterface if1 = new DerivedInterface() {}; + success &= testMapAny(transport, + new Any(new Type(BaseInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] { + null, if1 } }), + new CompareSpecific( + new BaseInterface[][] { + new BaseInterface[] { + null, if1 } })); + } + success &= testMapAny(transport, + new DerivedInterface[][] { + new DerivedInterface[] {} }, + new CompareBoxed()); + success &= testMapAny(transport, + new DerivedInterface[][] { + new DerivedInterface[] { + null, new DerivedInterface() {} } }, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] {} }), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any( + new Type(DerivedInterface[][].class), + new DerivedInterface[][] { + new DerivedInterface[] { + null, + new DerivedInterface() {} } }), + new CompareUnboxed()); + + // Enum Types: + if (createTypes) { + success &= testMapAny(transport, new Enum1(), new CompareBoxed()); + success &= testMapAny(transport, new Any(new Type(Enum1.class), + new Enum1()), + new CompareUnboxed()); + success &= testMapAny(transport, new Any(new Type(Enum1.class), + new Enum2()), + new CompareSpecific(new Enum1())); + } + + // Struct Types: + if (createTypes) { + success &= testMapAny(transport, new BaseStruct(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseStruct.class), + new BaseStruct()), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseStruct.class), + new DerivedStruct()), + new CompareSpecific(new BaseStruct())); + success &= testMapAny(transport, new DerivedStruct(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedStruct.class), + new DerivedStruct()), + new CompareUnboxed()); + } + + // Exception Types: + success &= testMapAny(transport, new com.sun.star.uno.Exception(), + new CompareClass( + com.sun.star.uno.Exception.class)); + success &= testMapAny(transport, + new Any(new Type( + com.sun.star.uno.Exception.class), + new com.sun.star.uno.Exception()), + new CompareClass( + com.sun.star.uno.Exception.class)); + success &= testMapAny(transport, + new Any(new Type( + com.sun.star.uno.Exception.class), + new BaseException()), + new CompareClass( + com.sun.star.uno.Exception.class)); + success &= testMapAny(transport, + new Any(new Type( + com.sun.star.uno.Exception.class), + new DerivedException()), + new CompareClass( + com.sun.star.uno.Exception.class)); + if (createTypes) { + success &= testMapAny(transport, new BaseException(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseException.class), + new BaseException()), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseException.class), + new DerivedException()), + new CompareSpecific(new BaseException())); + success &= testMapAny(transport, new DerivedException(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedException.class), + new DerivedException()), + new CompareUnboxed()); + } + success &= testMapAny(transport, + new com.sun.star.uno.RuntimeException(), + new CompareClass( + com.sun.star.uno.RuntimeException.class)); + success &= testMapAny(transport, + new Any( + new Type( + com.sun.star.uno.RuntimeException. + class), + new com.sun.star.uno.RuntimeException()), + new CompareClass( + com.sun.star.uno.RuntimeException.class)); + success &= testMapAny(transport, + new Any( + new Type( + com.sun.star.uno.RuntimeException. + class), + new BaseRuntimeException()), + new CompareClass( + com.sun.star.uno.RuntimeException.class)); + success &= testMapAny(transport, + new Any( + new Type( + com.sun.star.uno.RuntimeException. + class), + new DerivedRuntimeException()), + new CompareClass( + com.sun.star.uno.RuntimeException.class)); + if (createTypes) { + success &= testMapAny(transport, new BaseRuntimeException(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type( + BaseRuntimeException.class), + new BaseRuntimeException()), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type( + BaseRuntimeException.class), + new DerivedRuntimeException()), + new CompareSpecific( + new BaseRuntimeException())); + success &= testMapAny(transport, new DerivedRuntimeException(), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type( + DerivedRuntimeException.class), + new DerivedRuntimeException()), + new CompareUnboxed()); + } + + // Interface Types: + success &= testMapAny(transport, null, new CompareBoxed()); + success &= testMapAny(transport, new XInterface() {}, + new CompareBoxed()); + success &= testMapAny(transport, new BaseInterface() {}, + new CompareBoxed()); + success &= testMapAny(transport, new DerivedInterface() {}, + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface.class), null), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface.class), + new XInterface() {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface.class), + new BaseInterface() {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(XInterface.class), + new DerivedInterface() {}), + new CompareUnboxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface.class), null), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface.class), + new BaseInterface() {}), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(BaseInterface.class), + new DerivedInterface() {}), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedInterface.class), + null), + new CompareBoxed()); + success &= testMapAny(transport, + new Any(new Type(DerivedInterface.class), + new DerivedInterface() {}), + new CompareBoxed()); + + // Misc: + try { + transport.mapAny(new Object()); + System.out.println("BAD mapAny(Object), no exception"); + success = false; + } catch (StackOverflowError e) { + System.out.println("BAD mapAny(Object): " + e); + success = false; + } catch (RuntimeException e) {} + + return success; + } + + private TestAny() {} // do not instantiate + + private static boolean testType(Class zclass, TypeClass tclass, + String tname) { + Type t1 = new Type(zclass); + Type t2 = new Type(tname, tclass); + boolean ok = true; + if (t1.getTypeClass() != tclass) { + ok = false; + System.out.println("BAD Type(" + zclass + ").getTypeClass() = " + + t1.getTypeClass() + " != " + tclass); + } + if (!t1.getTypeName().equals(tname)) { + ok = false; + System.out.println("BAD Type(" + zclass + ").getTypeName() = " + + t1.getTypeName() + " != " + tname); + } + if (!t1.equals(t2)) { + ok = false; + System.out.println("BAD Type(" + zclass + ") != Type(" + tname + + ", " + tclass + ")"); + } + return ok; + } + + private static boolean testMapAny(XTransport transport, Object any, + Compare compare) { + Object any2 = transport.mapAny(any); + boolean eq = compare.equal(any, any2); + if (!eq) { + System.out.println("BAD mapAny(" + any + ") -> " + any2); + } + return eq; + } + + private static abstract class Compare { + public abstract boolean equal(Object o1, Object o2); + } + + private static final class CompareBoxed extends Compare { + public CompareBoxed() { + this(false); + } + + public CompareBoxed(boolean unboxInner) { + this.unboxInner = unboxInner; + } + + public boolean equal(Object o1, Object o2) { + if (o1 instanceof Any) { + return o2 instanceof Any + && ((Any) o1).getType().equals(((Any) o2).getType()) + && equalValues(((Any) o1).getObject(), + ((Any) o2).getObject()); + } else { + return equalValues(o1, o2); + } + } + + private boolean equalValues(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o1.getClass().isArray()) { + if (!(o2 != null && o1.getClass() == o2.getClass() + && Array.getLength(o1) == Array.getLength(o2))) { + return false; + } + for (int i = 0; i < Array.getLength(o1); ++i) { + Object oo1 = Array.get(o1, i); + if (unboxInner && oo1 instanceof Any) { + oo1 = ((Any) oo1).getObject(); + } + if (!equal(oo1, Array.get(o2, i))) { + return false; + } + } + return true; + } else { + return o1.equals(o2); + } + } + + private final boolean unboxInner; + } + + private static final class CompareUnboxed extends Compare { + public CompareUnboxed() { + this(false); + } + + public CompareUnboxed(boolean unboxInner) { + this.unboxInner = unboxInner; + } + + public boolean equal(Object o1, Object o2) { + return new CompareBoxed(unboxInner).equal(((Any) o1).getObject(), + o2); + } + + private final boolean unboxInner; + } + + private static final class CompareSpecific extends Compare { + public CompareSpecific(Object specific) { + this.specific = specific; + } + + public boolean equal(Object o1, Object o2) { + return new CompareBoxed().equal(specific, o2); + } + + private final Object specific; + } + + private static final class CompareClass extends Compare { + public CompareClass(Class clazz) { + this.clazz = clazz; + } + + public boolean equal(Object o1, Object o2) { + return o2 != null && o2.getClass() == clazz; + } + + private final Class clazz; + } + + public static class Enum1 extends Enum { + public Enum1() { + super(0); + } + + public static Enum1 fromInt(int value) { + return new Enum1(); + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == Enum1.class; + } + } + + public static class Enum2 extends Enum1 { + public boolean equals(Object obj) { + return obj != null && obj.getClass() == Enum2.class; + } + } + + public static class BaseStruct { + public boolean equals(Object obj) { + return obj != null && obj.getClass() == BaseStruct.class; + } + } + + public static class DerivedStruct extends BaseStruct { + public boolean equals(Object obj) { + return obj != null && obj.getClass() == DerivedStruct.class; + } + } + + public static class BaseException extends com.sun.star.uno.Exception { + public BaseException() {} + + public BaseException(String message) { + super(message); + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == BaseException.class; + } + } + + public static class DerivedException extends BaseException { + public DerivedException() {} + + public DerivedException(String message) { + super(message); + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == DerivedException.class; + } + } + + public static class BaseRuntimeException + extends com.sun.star.uno.RuntimeException + { + public BaseRuntimeException() {} + + public BaseRuntimeException(String message) { + super(message); + } + + public boolean equals(Object obj) { + return obj != null + && obj.getClass() == BaseRuntimeException.class; + } + } + + public static class DerivedRuntimeException extends BaseRuntimeException + { + public DerivedRuntimeException() {} + + public DerivedRuntimeException(String message) { + super(message); + } + + public boolean equals(Object obj) { + return obj != null + && obj.getClass() == DerivedRuntimeException.class; + } + } +} diff --git a/bridges/test/java_uno/any/TestJni.java b/bridges/test/java_uno/any/TestJni.java new file mode 100644 index 000000000000..1242c38e86b0 --- /dev/null +++ b/bridges/test/java_uno/any/TestJni.java @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.java_uno.anytest; + +public class TestJni +{ + static { System.loadLibrary( "test_javauno_any" ); } + private static native XTransport create_jni_transport(ClassLoader loader); + + public static void main( String args [] ) + { + if (TestAny.test( + create_jni_transport(TestJni.class.getClassLoader()), false )) + { + System.out.println( "jni any test succeeded." ); + } + else + { + System.err.println( "jni any test failed!" ); + System.exit( 1 ); + } + } +} diff --git a/bridges/test/java_uno/any/TestRemote.java b/bridges/test/java_uno/any/TestRemote.java new file mode 100644 index 000000000000..4d038559660f --- /dev/null +++ b/bridges/test/java_uno/any/TestRemote.java @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.java_uno.anytest; + +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.lib.TestBed; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +public final class TestRemote { + public static void main(String[] args) throws Exception { + boolean success = new TestBed().execute( + new Provider(), false, Client.class, 0); + System.out.println("success? " + success); + System.exit(success ? 0 : 1); + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTransport transport = UnoRuntime.queryInterface( + XTransport.class, getBridge(context).getInstance("Transport")); + return TestAny.test(transport, true); + } + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + return new XTransport() { + public Object mapAny(Object any) { + return any; + } + }; + } + } +} diff --git a/bridges/test/java_uno/any/makefile.mk b/bridges/test/java_uno/any/makefile.mk new file mode 100644 index 000000000000..888fae21d3d2 --- /dev/null +++ b/bridges/test/java_uno/any/makefile.mk @@ -0,0 +1,127 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +PRJNAME = bridges +TARGET = test_javauno_any + +PACKAGE = test$/java_uno$/anytest + +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk + +.IF "$(GUI)" == "WNT" +GIVE_EXEC_RIGHTS = @echo +.ELSE +GIVE_EXEC_RIGHTS = chmod +x +.ENDIF + +JAVAFILES = \ + $(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES))) + +# Make sure TestBed.class is found under $(CLASSDIR)$/test: +.IF "$(XCLASSPATH)" == "" +XCLASSPATH := $(CLASSDIR)$/test +.ELSE +XCLASSPATH !:= $(XCLASSPATH)$(PATH_SEPERATOR)$(CLASSDIR)$/test +.ENDIF + +EXEC_CLASSPATH_TMP = \ + $(foreach,i,$(JARFILES) $(SOLARBINDIR)$/$i)$(PATH_SEPERATOR)$(XCLASSPATH) +EXEC_CLASSPATH = \ + $(strip $(subst,!,$(PATH_SEPERATOR) $(EXEC_CLASSPATH_TMP:s/ /!/))) + +JARFILES = juh.jar jurt.jar ridl.jar +JAVACLASSFILES = \ + $(CLASSDIR)$/$(PACKAGE)$/TestAny.class \ + $(CLASSDIR)$/$(PACKAGE)$/TestRemote.class \ + $(CLASSDIR)$/$(PACKAGE)$/TestJni.class + +#-------------------------------------------------- + +USE_DEFFILE = TRUE +ENABLE_EXCEPTIONS = TRUE +INCPRE += $(OUT)$/inc$/test + +.IF "$(debug)" != "" +.IF "$(COM)" == "MSC" +CFLAGS += -Ob0 +.ENDIF +.ENDIF + +SLOFILES= \ + $(SLO)$/transport.obj + +SHL1TARGET=$(TARGET) + +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(JVMACCESSLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP=$(TARGET).map +SHL1IMPLIB=i$(TARGET) +SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +.INCLUDE: target.mk + +#-------------------------------------------------- + +$(SLOFILES) : $(MISC)$/gen_files.flag +$(JAVACLASSFILES) : $(MISC)$/gen_files.flag + +ALLTAR : \ + $(OUT)$/bin$/TestRemote \ + $(OUT)$/bin$/TestJni + +$(OUT)$/bin$/TestRemote : $(JAVACLASSFILES) + -rm -f $@ + echo java -classpath ..$/class$/test$(PATH_SEPERATOR)..$/class$(PATH_SEPERATOR)$(EXEC_CLASSPATH) \ + test.java_uno.anytest.TestRemote > $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(OUT)$/bin$/TestJni : $(JAVACLASSFILES) + -rm -f $@ + echo '$(AUGMENT_LIBRARY_PATH)' java -classpath \ + .$(PATH_SEPERATOR)..$/class$(PATH_SEPERATOR)$(EXEC_CLASSPATH) \ + -Djava.library.path=..$/lib test.java_uno.anytest.TestJni >> $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(BIN)$/test_java_uno_anytest.rdb : types.idl + $(IDLC) -I$(PRJ) -I$(SOLARIDLDIR) -O$(BIN) $? + $(REGMERGE) $@ /UCR $(BIN)$/{$(?:f:s/.idl/.urd/)} + +$(MISC)$/gen_files.flag : $(BIN)$/test_java_uno_anytest.rdb + $(CPPUMAKER) -C -BUCR -O $(OUT)$/inc$/test -X $(SOLARBINDIR)$/udkapi.rdb $? + $(CPPUMAKER) -C -BUCR -O $(OUT)$/inc$/test -T com.sun.star.uno.XInterface $(SOLARBINDIR)$/udkapi.rdb + $(JAVAMAKER) -nD -BUCR -O $(CLASSDIR) -X $(SOLARBINDIR)$/udkapi.rdb $? + $(TOUCH) $@ diff --git a/bridges/test/java_uno/any/test_javauno_any.map b/bridges/test/java_uno/any/test_javauno_any.map new file mode 100644 index 000000000000..c50f7b162db7 --- /dev/null +++ b/bridges/test/java_uno/any/test_javauno_any.map @@ -0,0 +1,6 @@ +UDK_3_0_0 { + global: + Java_test_java_1uno_anytest_TestJni_create_1jni_1transport; + local: + *; +}; diff --git a/bridges/test/java_uno/any/transport.cxx b/bridges/test/java_uno/any/transport.cxx new file mode 100644 index 000000000000..4211a96f8149 --- /dev/null +++ b/bridges/test/java_uno/any/transport.cxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "jni.h" + +#include "uno/mapping.hxx" +#include "uno/environment.hxx" +#include "jvmaccess/virtualmachine.hxx" +#include "jvmaccess/unovirtualmachine.hxx" +#include "cppuhelper/implbase1.hxx" + +#include "test/java_uno/anytest/XTransport.hpp" +#include "test/java_uno/anytest/DerivedInterface.hpp" + + +using namespace ::com::sun::star::uno; +using ::test::java_uno::anytest::XTransport; +using ::rtl::OUString; + +namespace +{ +//================================================================================================== +class Transport : public ::cppu::WeakImplHelper1< XTransport > +{ +public: + virtual Any SAL_CALL mapAny( Any const & any ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +Any Transport::mapAny( Any const & any ) + throw (RuntimeException) +{ + return any; +} +} + +//################################################################################################## +extern "C" JNIEXPORT jobject JNICALL Java_test_java_1uno_anytest_TestJni_create_1jni_1transport( + JNIEnv * jni_env, jclass, jobject loader ) + SAL_THROW_EXTERN_C() +{ + // publish some idl types + ::getCppuType( (Reference< XTransport > const *)0 ); + ::getCppuType( (Reference< ::test::java_uno::anytest::DerivedInterface > const *)0 ); + + Reference< XTransport > xRet( new Transport() ); + + // get java vm + JavaVM * java_vm; + OSL_VERIFY( 0 == jni_env->GetJavaVM( &java_vm ) ); + // create jvmaccess vm + ::rtl::Reference< ::jvmaccess::UnoVirtualMachine > vm; + try { + vm = new ::jvmaccess::UnoVirtualMachine( + new ::jvmaccess::VirtualMachine( + java_vm, JNI_VERSION_1_2, false, jni_env ), + loader ); + } catch ( ::jvmaccess::UnoVirtualMachine::CreationException & ) { + OSL_ASSERT( false ); + throw; + } + // create uno envs + OUString java_name( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_JAVA) ); + OUString cpp_name( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ); + Environment java_env, cpp_env; + uno_getEnvironment( (uno_Environment **)&java_env, java_name.pData, vm.get() ); + OSL_ASSERT( java_env.is() ); + uno_getEnvironment( (uno_Environment **)&cpp_env, cpp_name.pData, 0 ); + OSL_ASSERT( cpp_env.is() ); + + // map interface + Mapping mapping( cpp_env.get(), java_env.get() ); + OSL_ASSERT( mapping.is() ); + jobject jo_global = (jobject)mapping.mapInterface( xRet.get(), ::getCppuType( &xRet ) ); + OSL_ASSERT( 0 != jo_global ); + + // return + jobject jo_ret = jni_env->NewLocalRef( jo_global ); + jni_env->DeleteGlobalRef( jo_global ); + return jo_ret; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/java_uno/any/types.idl b/bridges/test/java_uno/any/types.idl new file mode 100644 index 000000000000..a7d7df5487e6 --- /dev/null +++ b/bridges/test/java_uno/any/types.idl @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/uno/XInterface.idl> + + +module test { module java_uno { module anytest { + +interface XTransport : com::sun::star::uno::XInterface +{ + any mapAny([in] any a); +}; + +interface BaseInterface : com::sun::star::uno::XInterface {}; + +interface DerivedInterface : BaseInterface {}; + +}; }; }; diff --git a/bridges/test/java_uno/equals/TestEquals.java b/bridges/test/java_uno/equals/TestEquals.java new file mode 100644 index 000000000000..9d7139b11b8c --- /dev/null +++ b/bridges/test/java_uno/equals/TestEquals.java @@ -0,0 +1,1304 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.java_uno.equals; + +import com.sun.star.bridge.XBridge; +import com.sun.star.bridge.XBridgeFactory; +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.comp.helper.Bootstrap; +import com.sun.star.connection.Acceptor; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.TestBed; +import com.sun.star.lib.uno.typeinfo.MethodTypeInfo; +import com.sun.star.lib.uno.typeinfo.TypeInfo; +import com.sun.star.loader.XImplementationLoader; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.XInterface; +import java.io.File; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Hashtable; + +// In this test scenario, the Java server (see implementation of method +// notifyAccepting) has a remote bridge to the Java client and a local JNI +// bridge to a C++ com.sun.star.test.bridges.testequals.impl service. The C++ +// service and the Java client are also connected via a remote bridge. +// +// The Java server gets two objects (INSTANCE1, INSTANCE2), once directly from +// the Java client via the remote bridge (proxies test1A, test2A), and once +// through the C++ service via the JNI bridge (proxies test1B, test2B). +// Exhaustive tests on the proxies' equals and hashCode methods are done. + +public final class TestEquals { + // args[0] must be a file system path to a types.rdb, + // args[1] must be a file system path to a services.rdb + public static void main(String[] args) throws Exception { + TestBed t = new TestBed(); + boolean success = t.execute( + new Provider(t, toFileUrl(args[0]), toFileUrl(args[1])), true, + Client.class, 0); + System.out.println("success? " + success); + System.exit(success ? 0 : 1); + } + + private static String toFileUrl(String path) throws MalformedURLException { + String url = new File(path).toURI().toURL().toString(); + String prefix = "file:/"; + if (url.startsWith(prefix) + && (url.length() == prefix.length() + || url.charAt(prefix.length()) != '/')) { + url = url.substring(0, prefix.length()) + "//" + + url.substring(prefix.length()); + } + return url; + } + + public static final class Client extends TestBed.Client { + public static void main(String[] args) { + new Client().execute(); + } + + protected boolean run(XComponentContext context) throws Throwable { + XTestFrame f = UnoRuntime.queryInterface( + XTestFrame.class, getBridge(context).getInstance("TestFrame")); + XAcceptor acceptor = Acceptor.create(context); + XBridgeFactory factory = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + System.out.println("Client, 2nd connection: Accepting..."); + XInstanceProvider prov = new Provider(); + f.notifyAccepting(new Done(), prov.getInstance(INSTANCE1), + prov.getInstance(INSTANCE2)); + XConnection connection = acceptor.accept(CONNECTION_DESCRIPTION); + System.out.println("Client, 2nd connection: ...connected..."); + XBridge bridge2 = factory.createBridge( + "", PROTOCOL_DESCRIPTION, connection, prov); + System.out.println("Client, 2nd connection: ...bridged."); + synchronized (lock) { + while (!done) { + lock.wait(); + } + } + return true; + } + + private static final class Provider implements XInstanceProvider { + public Object getInstance(String instanceName) { + synchronized (map) { + Object o = map.get(instanceName); + if (o == null) { + o = new XDerived() {}; + map.put(instanceName, o); + } + return o; + } + } + + private final HashMap map = new HashMap(); + } + + private final class Done implements XDone { + public void notifyDone() { + synchronized (lock) { + done = true; + lock.notifyAll(); + } + } + } + + private final Object lock = new Object(); + private boolean done = false; + } + + private static final class Provider implements XInstanceProvider { + public Provider(TestBed testBed, String unoTypes, String unoServices) { + this.testBed = testBed; + this.unoTypes = unoTypes; + this.unoServices = unoServices; + } + + public Object getInstance(String instanceName) { + return new XTestFrame() { + public void notifyAccepting( + final XDone done, final Object object1, + final Object object2) + { + new Thread() { + public void run() { + try { + Object test1Aa = object1; + XBase test1Ab = UnoRuntime.queryInterface( + XBase.class, test1Aa); + XDerived test1Ac = + UnoRuntime.queryInterface( + XDerived.class, test1Aa); + Object test2Aa = object2; + XBase test2Ab = UnoRuntime.queryInterface( + XBase.class, test2Aa); + XDerived test2Ac = + UnoRuntime.queryInterface( + XDerived.class, test2Aa); + + Hashtable params = new Hashtable(); + params.put("UNO_TYPES", unoTypes); + params.put("UNO_SERVICES", unoServices); + XComponentContext context = Bootstrap. + defaultBootstrap_InitialComponentContext( + null, params); + XMultiComponentFactory factory + = context.getServiceManager(); + XImplementationLoader loader = + UnoRuntime.queryInterface( + XImplementationLoader.class, + factory.createInstanceWithContext( + "com.sun.star.loader." + + "SharedLibrary", + context)); + XSingleComponentFactory factory2 = + UnoRuntime.queryInterface( + XSingleComponentFactory.class, + loader.activate( + "com.sun.star.test.bridges." + + "testequals.impl", + "", "../lib/testequals.uno", + null)); + XTestInterface test = + UnoRuntime.queryInterface( + XTestInterface.class, + factory2.createInstanceWithContext( + context)); + // allow client to start accepting: + Thread.sleep(3000); + test.connect( + CONNECTION_DESCRIPTION, + PROTOCOL_DESCRIPTION); + + Object test1Ba = test.get(INSTANCE1); + XBase test1Bb = UnoRuntime.queryInterface( + XBase.class, test1Ba); + XDerived test1Bc = + UnoRuntime.queryInterface( + XDerived.class, test1Ba); + Object test2Ba = test.get(INSTANCE2); + XBase test2Bb = UnoRuntime.queryInterface( + XBase.class, test2Ba); + XDerived test2Bc = + UnoRuntime.queryInterface( + XDerived.class, test2Ba); + + boolean success = true; + + success &= test( + "UnoRumtime.areSame(null, null)", + UnoRuntime.areSame(null, null)); + success &= test( + "!UnoRumtime.areSame(null, test1Aa)", + !UnoRuntime.areSame(null, test1Aa)); + success &= test( + "!UnoRumtime.areSame(null, test1Ab)", + !UnoRuntime.areSame(null, test1Ab)); + success &= test( + "!UnoRumtime.areSame(null, test1Ac)", + !UnoRuntime.areSame(null, test1Ac)); + success &= test( + "!UnoRumtime.areSame(null, test1Ba)", + !UnoRuntime.areSame(null, test1Ba)); + success &= test( + "!UnoRumtime.areSame(null, test1Bb)", + !UnoRuntime.areSame(null, test1Bb)); + success &= test( + "!UnoRumtime.areSame(null, test1Bc)", + !UnoRuntime.areSame(null, test1Bc)); + success &= test( + "!UnoRumtime.areSame(null, test2Aa)", + !UnoRuntime.areSame(null, test2Aa)); + success &= test( + "!UnoRumtime.areSame(null, test2Ab)", + !UnoRuntime.areSame(null, test2Ab)); + success &= test( + "!UnoRumtime.areSame(null, test2Ac)", + !UnoRuntime.areSame(null, test2Ac)); + success &= test( + "!UnoRumtime.areSame(null, test2Ba)", + !UnoRuntime.areSame(null, test2Ba)); + success &= test( + "!UnoRumtime.areSame(null, test2Bb)", + !UnoRuntime.areSame(null, test2Bb)); + success &= test( + "!UnoRumtime.areSame(null, test2Bc)", + !UnoRuntime.areSame(null, test2Bc)); + + success &= test( + "!test1Aa.equals(null)", + !test1Aa.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Aa, null)", + !UnoRuntime.areSame(test1Aa, null)); + success &= test( + "test1Aa.equals(test1Aa)", + test1Aa.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Aa)", + UnoRuntime.areSame(test1Aa, test1Aa)); + success &= test( + "test1Aa.equals(test1Ab)", + test1Aa.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Ab)", + UnoRuntime.areSame(test1Aa, test1Ab)); + success &= test( + "test1Aa.equals(test1Ac)", + test1Aa.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Ac)", + UnoRuntime.areSame(test1Aa, test1Ac)); + success &= test( + "test1Aa.equals(test1Ba)", + test1Aa.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Ba)", + UnoRuntime.areSame(test1Aa, test1Ba)); + success &= test( + "test1Aa.equals(test1Bb)", + test1Aa.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Bb)", + UnoRuntime.areSame(test1Aa, test1Bb)); + success &= test( + "test1Aa.equals(test1Bc)", + test1Aa.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Aa, test1Bc)", + UnoRuntime.areSame(test1Aa, test1Bc)); + success &= test( + "!test1Aa.equals(test2Aa)", + !test1Aa.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Aa)", + !UnoRuntime.areSame(test1Aa, test2Aa)); + success &= test( + "!test1Aa.equals(test2Ab)", + !test1Aa.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Ab)", + !UnoRuntime.areSame(test1Aa, test2Ab)); + success &= test( + "!test1Aa.equals(test2Ac)", + !test1Aa.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Ac)", + !UnoRuntime.areSame(test1Aa, test2Ac)); + success &= test( + "!test1Aa.equals(test2Ba)", + !test1Aa.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Ba)", + !UnoRuntime.areSame(test1Aa, test2Ba)); + success &= test( + "!test1Aa.equals(test2Bb)", + !test1Aa.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Bb)", + !UnoRuntime.areSame(test1Aa, test2Bb)); + success &= test( + "!test1Aa.equals(test2Bc)", + !test1Aa.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Aa, test2Bc)", + !UnoRuntime.areSame(test1Aa, test2Bc)); + + success &= test( + "!test1Ab.equals(null)", + !test1Ab.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Ab, null)", + !UnoRuntime.areSame(test1Ab, null)); + success &= test( + "test1Ab.equals(test1Aa)", + test1Ab.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Aa)", + UnoRuntime.areSame(test1Ab, test1Aa)); + success &= test( + "test1Ab.equals(test1Ab)", + test1Ab.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Ab)", + UnoRuntime.areSame(test1Ab, test1Ab)); + success &= test( + "test1Ab.equals(test1Ac)", + test1Ab.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Ac)", + UnoRuntime.areSame(test1Ab, test1Ac)); + success &= test( + "test1Ab.equals(test1Ba)", + test1Ab.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Ba)", + UnoRuntime.areSame(test1Ab, test1Ba)); + success &= test( + "test1Ab.equals(test1Bb)", + test1Ab.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Bb)", + UnoRuntime.areSame(test1Ab, test1Bb)); + success &= test( + "test1Ab.equals(test1Bc)", + test1Ab.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Ab, test1Bc)", + UnoRuntime.areSame(test1Ab, test1Bc)); + success &= test( + "!test1Ab.equals(test2Aa)", + !test1Ab.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Aa)", + !UnoRuntime.areSame(test1Ab, test2Aa)); + success &= test( + "!test1Ab.equals(test2Ab)", + !test1Ab.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Ab)", + !UnoRuntime.areSame(test1Ab, test2Ab)); + success &= test( + "!test1Ab.equals(test2Ac)", + !test1Ab.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Ac)", + !UnoRuntime.areSame(test1Ab, test2Ac)); + success &= test( + "!test1Ab.equals(test2Ba)", + !test1Ab.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Ba)", + !UnoRuntime.areSame(test1Ab, test2Ba)); + success &= test( + "!test1Ab.equals(test2Bb)", + !test1Ab.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Bb)", + !UnoRuntime.areSame(test1Ab, test2Bb)); + success &= test( + "!test1Ab.equals(test2Bc)", + !test1Ab.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Ab, test2Bc)", + !UnoRuntime.areSame(test1Ab, test2Bc)); + + success &= test( + "!test1Ac.equals(null)", + !test1Ac.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Ac, null)", + !UnoRuntime.areSame(test1Ac, null)); + success &= test( + "test1Ac.equals(test1Aa)", + test1Ac.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Aa)", + UnoRuntime.areSame(test1Ac, test1Aa)); + success &= test( + "test1Ac.equals(test1Ab)", + test1Ac.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Ab)", + UnoRuntime.areSame(test1Ac, test1Ab)); + success &= test( + "test1Ac.equals(test1Ac)", + test1Ac.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Ac)", + UnoRuntime.areSame(test1Ac, test1Ac)); + success &= test( + "test1Ac.equals(test1Ba)", + test1Ac.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Ba)", + UnoRuntime.areSame(test1Ac, test1Ba)); + success &= test( + "test1Ac.equals(test1Bb)", + test1Ac.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Bb)", + UnoRuntime.areSame(test1Ac, test1Bb)); + success &= test( + "test1Ac.equals(test1Bc)", + test1Ac.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Ac, test1Bc)", + UnoRuntime.areSame(test1Ac, test1Bc)); + success &= test( + "!test1Ac.equals(test2Aa)", + !test1Ac.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Aa)", + !UnoRuntime.areSame(test1Ac, test2Aa)); + success &= test( + "!test1Ac.equals(test2Ab)", + !test1Ac.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Ab)", + !UnoRuntime.areSame(test1Ac, test2Ab)); + success &= test( + "!test1Ac.equals(test2Ac)", + !test1Ac.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Ac)", + !UnoRuntime.areSame(test1Ac, test2Ac)); + success &= test( + "!test1Ac.equals(test2Ba)", + !test1Ac.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Ba)", + !UnoRuntime.areSame(test1Ac, test2Ba)); + success &= test( + "!test1Ac.equals(test2Bb)", + !test1Ac.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Bb)", + !UnoRuntime.areSame(test1Ac, test2Bb)); + success &= test( + "!test1Ac.equals(test2Bc)", + !test1Ac.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Ac, test2Bc)", + !UnoRuntime.areSame(test1Ac, test2Bc)); + + success &= test( + "!test1Ba.equals(null)", + !test1Ba.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Ba, null)", + !UnoRuntime.areSame(test1Ba, null)); + success &= test( + "test1Ba.equals(test1Aa)", + test1Ba.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Aa)", + UnoRuntime.areSame(test1Ba, test1Aa)); + success &= test( + "test1Ba.equals(test1Ab)", + test1Ba.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Ab)", + UnoRuntime.areSame(test1Ba, test1Ab)); + success &= test( + "test1Ba.equals(test1Ac)", + test1Ba.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Ac)", + UnoRuntime.areSame(test1Ba, test1Ac)); + success &= test( + "test1Ba.equals(test1Ba)", + test1Ba.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Ba)", + UnoRuntime.areSame(test1Ba, test1Ba)); + success &= test( + "test1Ba.equals(test1Bb)", + test1Ba.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Bb)", + UnoRuntime.areSame(test1Ba, test1Bb)); + success &= test( + "test1Ba.equals(test1Bc)", + test1Ba.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Ba, test1Bc)", + UnoRuntime.areSame(test1Ba, test1Bc)); + success &= test( + "!test1Ba.equals(test2Aa)", + !test1Ba.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Aa)", + !UnoRuntime.areSame(test1Ba, test2Aa)); + success &= test( + "!test1Ba.equals(test2Ab)", + !test1Ba.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Ab)", + !UnoRuntime.areSame(test1Ba, test2Ab)); + success &= test( + "!test1Ba.equals(test2Ac)", + !test1Ba.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Ac)", + !UnoRuntime.areSame(test1Ba, test2Ac)); + success &= test( + "!test1Ba.equals(test2Ba)", + !test1Ba.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Ba)", + !UnoRuntime.areSame(test1Ba, test2Ba)); + success &= test( + "!test1Ba.equals(test2Bb)", + !test1Ba.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Bb)", + !UnoRuntime.areSame(test1Ba, test2Bb)); + success &= test( + "!test1Ba.equals(test2Bc)", + !test1Ba.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Ba, test2Bc)", + !UnoRuntime.areSame(test1Ba, test2Bc)); + + success &= test( + "!test1Bb.equals(null)", + !test1Bb.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Bb, null)", + !UnoRuntime.areSame(test1Bb, null)); + success &= test( + "test1Bb.equals(test1Aa)", + test1Bb.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Aa)", + UnoRuntime.areSame(test1Bb, test1Aa)); + success &= test( + "test1Bb.equals(test1Ab)", + test1Bb.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Ab)", + UnoRuntime.areSame(test1Bb, test1Ab)); + success &= test( + "test1Bb.equals(test1Ac)", + test1Bb.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Ac)", + UnoRuntime.areSame(test1Bb, test1Ac)); + success &= test( + "test1Bb.equals(test1Ba)", + test1Bb.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Ba)", + UnoRuntime.areSame(test1Bb, test1Ba)); + success &= test( + "test1Bb.equals(test1Bb)", + test1Bb.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Bb)", + UnoRuntime.areSame(test1Bb, test1Bb)); + success &= test( + "test1Bb.equals(test1Bc)", + test1Bb.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Bb, test1Bc)", + UnoRuntime.areSame(test1Bb, test1Bc)); + success &= test( + "!test1Bb.equals(test2Aa)", + !test1Bb.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Aa)", + !UnoRuntime.areSame(test1Bb, test2Aa)); + success &= test( + "!test1Bb.equals(test2Ab)", + !test1Bb.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Ab)", + !UnoRuntime.areSame(test1Bb, test2Ab)); + success &= test( + "!test1Bb.equals(test2Ac)", + !test1Bb.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Ac)", + !UnoRuntime.areSame(test1Bb, test2Ac)); + success &= test( + "!test1Bb.equals(test2Ba)", + !test1Bb.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Ba)", + !UnoRuntime.areSame(test1Bb, test2Ba)); + success &= test( + "!test1Bb.equals(test2Bb)", + !test1Bb.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Bb)", + !UnoRuntime.areSame(test1Bb, test2Bb)); + success &= test( + "!test1Bb.equals(test2Bc)", + !test1Bb.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Bb, test2Bc)", + !UnoRuntime.areSame(test1Bb, test2Bc)); + + success &= test( + "!test1Bc.equals(null)", + !test1Bc.equals(null)); + success &= test( + "!UnoRuntime.areSame(test1Bc, null)", + !UnoRuntime.areSame(test1Bc, null)); + success &= test( + "test1Bc.equals(test1Aa)", + test1Bc.equals(test1Aa)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Aa)", + UnoRuntime.areSame(test1Bc, test1Aa)); + success &= test( + "test1Bc.equals(test1Ab)", + test1Bc.equals(test1Ab)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Ab)", + UnoRuntime.areSame(test1Bc, test1Ab)); + success &= test( + "test1Bc.equals(test1Ac)", + test1Bc.equals(test1Ac)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Ac)", + UnoRuntime.areSame(test1Bc, test1Ac)); + success &= test( + "test1Bc.equals(test1Ba)", + test1Bc.equals(test1Ba)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Ba)", + UnoRuntime.areSame(test1Bc, test1Ba)); + success &= test( + "test1Bc.equals(test1Bb)", + test1Bc.equals(test1Bb)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Bb)", + UnoRuntime.areSame(test1Bc, test1Bb)); + success &= test( + "test1Bc.equals(test1Bc)", + test1Bc.equals(test1Bc)); + success &= test( + "UnoRuntime.areSame(test1Bc, test1Bc)", + UnoRuntime.areSame(test1Bc, test1Bc)); + success &= test( + "!test1Bc.equals(test2Aa)", + !test1Bc.equals(test2Aa)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Aa)", + !UnoRuntime.areSame(test1Bc, test2Aa)); + success &= test( + "!test1Bc.equals(test2Ab)", + !test1Bc.equals(test2Ab)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Ab)", + !UnoRuntime.areSame(test1Bc, test2Ab)); + success &= test( + "!test1Bc.equals(test2Ac)", + !test1Bc.equals(test2Ac)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Ac)", + !UnoRuntime.areSame(test1Bc, test2Ac)); + success &= test( + "!test1Bc.equals(test2Ba)", + !test1Bc.equals(test2Ba)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Ba)", + !UnoRuntime.areSame(test1Bc, test2Ba)); + success &= test( + "!test1Bc.equals(test2Bb)", + !test1Bc.equals(test2Bb)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Bb)", + !UnoRuntime.areSame(test1Bc, test2Bb)); + success &= test( + "!test1Bc.equals(test2Bc)", + !test1Bc.equals(test2Bc)); + success &= test( + "!UnoRuntime.areSame(test1Bc, test2Bc)", + !UnoRuntime.areSame(test1Bc, test2Bc)); + + success &= test( + "!test2Aa.equals(null)", + !test2Aa.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Aa, null)", + !UnoRuntime.areSame(test2Aa, null)); + success &= test( + "!test2Aa.equals(test1Aa)", + !test2Aa.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Aa)", + !UnoRuntime.areSame(test2Aa, test1Aa)); + success &= test( + "!test2Aa.equals(test1Ab)", + !test2Aa.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Ab)", + !UnoRuntime.areSame(test2Aa, test1Ab)); + success &= test( + "!test2Aa.equals(test1Ac)", + !test2Aa.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Ac)", + !UnoRuntime.areSame(test2Aa, test1Ac)); + success &= test( + "!test2Aa.equals(test1Ba)", + !test2Aa.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Ba)", + !UnoRuntime.areSame(test2Aa, test1Ba)); + success &= test( + "!test2Aa.equals(test1Bb)", + !test2Aa.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Bb)", + !UnoRuntime.areSame(test2Aa, test1Bb)); + success &= test( + "!test2Aa.equals(test1Bc)", + !test2Aa.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Aa, test1Bc)", + !UnoRuntime.areSame(test2Aa, test1Bc)); + success &= test( + "test2Aa.equals(test2Aa)", + test2Aa.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Aa)", + UnoRuntime.areSame(test2Aa, test2Aa)); + success &= test( + "test2Aa.equals(test2Ab)", + test2Aa.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Ab)", + UnoRuntime.areSame(test2Aa, test2Ab)); + success &= test( + "test2Aa.equals(test2Ac)", + test2Aa.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Ac)", + UnoRuntime.areSame(test2Aa, test2Ac)); + success &= test( + "test2Aa.equals(test2Ba)", + test2Aa.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Ba)", + UnoRuntime.areSame(test2Aa, test2Ba)); + success &= test( + "test2Aa.equals(test2Bb)", + test2Aa.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Bb)", + UnoRuntime.areSame(test2Aa, test2Bb)); + success &= test( + "test2Aa.equals(test2Bc)", + test2Aa.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Aa, test2Bc)", + UnoRuntime.areSame(test2Aa, test2Bc)); + + success &= test( + "!test2Ab.equals(null)", + !test2Ab.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Ab, null)", + !UnoRuntime.areSame(test2Ab, null)); + success &= test( + "!test2Ab.equals(test1Aa)", + !test2Ab.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Aa)", + !UnoRuntime.areSame(test2Ab, test1Aa)); + success &= test( + "!test2Ab.equals(test1Ab)", + !test2Ab.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Ab)", + !UnoRuntime.areSame(test2Ab, test1Ab)); + success &= test( + "!test2Ab.equals(test1Ac)", + !test2Ab.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Ac)", + !UnoRuntime.areSame(test2Ab, test1Ac)); + success &= test( + "!test2Ab.equals(test1Ba)", + !test2Ab.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Ba)", + !UnoRuntime.areSame(test2Ab, test1Ba)); + success &= test( + "!test2Ab.equals(test1Bb)", + !test2Ab.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Bb)", + !UnoRuntime.areSame(test2Ab, test1Bb)); + success &= test( + "!test2Ab.equals(test1Bc)", + !test2Ab.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Ab, test1Bc)", + !UnoRuntime.areSame(test2Ab, test1Bc)); + success &= test( + "test2Ab.equals(test2Aa)", + test2Ab.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Aa)", + UnoRuntime.areSame(test2Ab, test2Aa)); + success &= test( + "test2Ab.equals(test2Ab)", + test2Ab.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Ab)", + UnoRuntime.areSame(test2Ab, test2Ab)); + success &= test( + "test2Ab.equals(test2Ac)", + test2Ab.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Ac)", + UnoRuntime.areSame(test2Ab, test2Ac)); + success &= test( + "test2Ab.equals(test2Ba)", + test2Ab.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Ba)", + UnoRuntime.areSame(test2Ab, test2Ba)); + success &= test( + "test2Ab.equals(test2Bb)", + test2Ab.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Bb)", + UnoRuntime.areSame(test2Ab, test2Bb)); + success &= test( + "test2Ab.equals(test2Bc)", + test2Ab.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Ab, test2Bc)", + UnoRuntime.areSame(test2Ab, test2Bc)); + + success &= test( + "!test2Ac.equals(null)", + !test2Ac.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Ac, null)", + !UnoRuntime.areSame(test2Ac, null)); + success &= test( + "!test2Ac.equals(test1Aa)", + !test2Ac.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Aa)", + !UnoRuntime.areSame(test2Ac, test1Aa)); + success &= test( + "!test2Ac.equals(test1Ab)", + !test2Ac.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Ab)", + !UnoRuntime.areSame(test2Ac, test1Ab)); + success &= test( + "!test2Ac.equals(test1Ac)", + !test2Ac.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Ac)", + !UnoRuntime.areSame(test2Ac, test1Ac)); + success &= test( + "!test2Ac.equals(test1Ba)", + !test2Ac.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Ba)", + !UnoRuntime.areSame(test2Ac, test1Ba)); + success &= test( + "!test2Ac.equals(test1Bb)", + !test2Ac.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Bb)", + !UnoRuntime.areSame(test2Ac, test1Bb)); + success &= test( + "!test2Ac.equals(test1Bc)", + !test2Ac.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Ac, test1Bc)", + !UnoRuntime.areSame(test2Ac, test1Bc)); + success &= test( + "test2Ac.equals(test2Aa)", + test2Ac.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Aa)", + UnoRuntime.areSame(test2Ac, test2Aa)); + success &= test( + "test2Ac.equals(test2Ab)", + test2Ac.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Ab)", + UnoRuntime.areSame(test2Ac, test2Ab)); + success &= test( + "test2Ac.equals(test2Ac)", + test2Ac.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Ac)", + UnoRuntime.areSame(test2Ac, test2Ac)); + success &= test( + "test2Ac.equals(test2Ba)", + test2Ac.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Ba)", + UnoRuntime.areSame(test2Ac, test2Ba)); + success &= test( + "test2Ac.equals(test2Bb)", + test2Ac.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Bb)", + UnoRuntime.areSame(test2Ac, test2Bb)); + success &= test( + "test2Ac.equals(test2Bc)", + test2Ac.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Ac, test2Bc)", + UnoRuntime.areSame(test2Ac, test2Bc)); + + success &= test( + "!test2Ba.equals(null)", + !test2Ba.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Ba, null)", + !UnoRuntime.areSame(test2Ba, null)); + success &= test( + "!test2Ba.equals(test1Aa)", + !test2Ba.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Aa)", + !UnoRuntime.areSame(test2Ba, test1Aa)); + success &= test( + "!test2Ba.equals(test1Ab)", + !test2Ba.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Ab)", + !UnoRuntime.areSame(test2Ba, test1Ab)); + success &= test( + "!test2Ba.equals(test1Ac)", + !test2Ba.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Ac)", + !UnoRuntime.areSame(test2Ba, test1Ac)); + success &= test( + "!test2Ba.equals(test1Ba)", + !test2Ba.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Ba)", + !UnoRuntime.areSame(test2Ba, test1Ba)); + success &= test( + "!test2Ba.equals(test1Bb)", + !test2Ba.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Bb)", + !UnoRuntime.areSame(test2Ba, test1Bb)); + success &= test( + "!test2Ba.equals(test1Bc)", + !test2Ba.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Ba, test1Bc)", + !UnoRuntime.areSame(test2Ba, test1Bc)); + success &= test( + "test2Ba.equals(test2Aa)", + test2Ba.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Aa)", + UnoRuntime.areSame(test2Ba, test2Aa)); + success &= test( + "test2Ba.equals(test2Ab)", + test2Ba.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Ab)", + UnoRuntime.areSame(test2Ba, test2Ab)); + success &= test( + "test2Ba.equals(test2Ac)", + test2Ba.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Ac)", + UnoRuntime.areSame(test2Ba, test2Ac)); + success &= test( + "test2Ba.equals(test2Ba)", + test2Ba.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Ba)", + UnoRuntime.areSame(test2Ba, test2Ba)); + success &= test( + "test2Ba.equals(test2Bb)", + test2Ba.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Bb)", + UnoRuntime.areSame(test2Ba, test2Bb)); + success &= test( + "test2Ba.equals(test2Bc)", + test2Ba.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Ba, test2Bc)", + UnoRuntime.areSame(test2Ba, test2Bc)); + + success &= test( + "!test2Bb.equals(null)", + !test2Bb.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Bb, null)", + !UnoRuntime.areSame(test2Bb, null)); + success &= test( + "!test2Bb.equals(test1Aa)", + !test2Bb.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Aa)", + !UnoRuntime.areSame(test2Bb, test1Aa)); + success &= test( + "!test2Bb.equals(test1Ab)", + !test2Bb.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Ab)", + !UnoRuntime.areSame(test2Bb, test1Ab)); + success &= test( + "!test2Bb.equals(test1Ac)", + !test2Bb.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Ac)", + !UnoRuntime.areSame(test2Bb, test1Ac)); + success &= test( + "!test2Bb.equals(test1Ba)", + !test2Bb.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Ba)", + !UnoRuntime.areSame(test2Bb, test1Ba)); + success &= test( + "!test2Bb.equals(test1Bb)", + !test2Bb.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Bb)", + !UnoRuntime.areSame(test2Bb, test1Bb)); + success &= test( + "!test2Bb.equals(test1Bc)", + !test2Bb.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Bb, test1Bc)", + !UnoRuntime.areSame(test2Bb, test1Bc)); + success &= test( + "test2Bb.equals(test2Aa)", + test2Bb.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Aa)", + UnoRuntime.areSame(test2Bb, test2Aa)); + success &= test( + "test2Bb.equals(test2Ab)", + test2Bb.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Ab)", + UnoRuntime.areSame(test2Bb, test2Ab)); + success &= test( + "test2Bb.equals(test2Ac)", + test2Bb.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Ac)", + UnoRuntime.areSame(test2Bb, test2Ac)); + success &= test( + "test2Bb.equals(test2Ba)", + test2Bb.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Ba)", + UnoRuntime.areSame(test2Bb, test2Ba)); + success &= test( + "test2Bb.equals(test2Bb)", + test2Bb.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Bb)", + UnoRuntime.areSame(test2Bb, test2Bb)); + success &= test( + "test2Bb.equals(test2Bc)", + test2Bb.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Bb, test2Bc)", + UnoRuntime.areSame(test2Bb, test2Bc)); + + success &= test( + "!test2Bc.equals(null)", + !test2Bc.equals(null)); + success &= test( + "!UnoRuntime.areSame(test2Bc, null)", + !UnoRuntime.areSame(test2Bc, null)); + success &= test( + "!test2Bc.equals(test1Aa)", + !test2Bc.equals(test1Aa)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Aa)", + !UnoRuntime.areSame(test2Bc, test1Aa)); + success &= test( + "!test2Bc.equals(test1Ab)", + !test2Bc.equals(test1Ab)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Ab)", + !UnoRuntime.areSame(test2Bc, test1Ab)); + success &= test( + "!test2Bc.equals(test1Ac)", + !test2Bc.equals(test1Ac)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Ac)", + !UnoRuntime.areSame(test2Bc, test1Ac)); + success &= test( + "!test2Bc.equals(test1Ba)", + !test2Bc.equals(test1Ba)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Ba)", + !UnoRuntime.areSame(test2Bc, test1Ba)); + success &= test( + "!test2Bc.equals(test1Bb)", + !test2Bc.equals(test1Bb)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Bb)", + !UnoRuntime.areSame(test2Bc, test1Bb)); + success &= test( + "!test2Bc.equals(test1Bc)", + !test2Bc.equals(test1Bc)); + success &= test( + "!UnoRuntime.areSame(test2Bc, test1Bc)", + !UnoRuntime.areSame(test2Bc, test1Bc)); + success &= test( + "test2Bc.equals(test2Aa)", + test2Bc.equals(test2Aa)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Aa)", + UnoRuntime.areSame(test2Bc, test2Aa)); + success &= test( + "test2Bc.equals(test2Ab)", + test2Bc.equals(test2Ab)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Ab)", + UnoRuntime.areSame(test2Bc, test2Ab)); + success &= test( + "test2Bc.equals(test2Ac)", + test2Bc.equals(test2Ac)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Ac)", + UnoRuntime.areSame(test2Bc, test2Ac)); + success &= test( + "test2Bc.equals(test2Ba)", + test2Bc.equals(test2Ba)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Ba)", + UnoRuntime.areSame(test2Bc, test2Ba)); + success &= test( + "test2Bc.equals(test2Bb)", + test2Bc.equals(test2Bb)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Bb)", + UnoRuntime.areSame(test2Bc, test2Bb)); + success &= test( + "test2Bc.equals(test2Bc)", + test2Bc.equals(test2Bc)); + success &= test( + "UnoRuntime.areSame(test2Bc, test2Bc)", + UnoRuntime.areSame(test2Bc, test2Bc)); + + success &= test( + "test1Aa.hashCode() == test1Ab.hashCode()", + test1Aa.hashCode() + == test1Ab.hashCode()); + success &= test( + "test1Aa.hashCode()" + + " == test1Ac.hashCode()", + test1Aa.hashCode() + == test1Ac.hashCode()); + success &= test( + "test1Aa.hashCode()" + + " == test1Ba.hashCode()", + test1Aa.hashCode() + == test1Ba.hashCode()); + success &= test( + "test1Aa.hashCode()" + + " == test1Bb.hashCode()", + test1Aa.hashCode() + == test1Bb.hashCode()); + success &= test( + "test1Aa.hashCode()" + + " == test1Bc.hashCode()", + test1Aa.hashCode() + == test1Bc.hashCode()); + success &= test( + "test2Aa.hashCode()" + + " == test2Ab.hashCode()", + test2Aa.hashCode() + == test2Ab.hashCode()); + success &= test( + "test2Aa.hashCode()" + + " == test2Ac.hashCode()", + test2Aa.hashCode() + == test2Ac.hashCode()); + success &= test( + "test2Aa.hashCode()" + + " == test2Ba.hashCode()", + test2Aa.hashCode() + == test2Ba.hashCode()); + success &= test( + "test2Aa.hashCode()" + + " == test2Bb.hashCode()", + test2Aa.hashCode() + == test2Bb.hashCode()); + success &= test( + "test2Aa.hashCode()" + + " == test2Bc.hashCode()", + test2Aa.hashCode() + == test2Bc.hashCode()); + + done.notifyDone(); + testBed.serverDone(success); + } catch (Exception e) { + e.printStackTrace(System.err); + } + }; + + private /*static*/ boolean test( + String message, boolean condition) + { + if (!condition) { + System.err.println("Failed: " + message); + } + return condition; + } + }.start(); + } + }; + } + + private final TestBed testBed; + private final String unoTypes; + private final String unoServices; + } + + public interface XDone extends XInterface { + void notifyDone(); + + TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("notifyDone", 0, 0) }; + } + + public interface XTestFrame extends XInterface { + void notifyAccepting(XDone done, Object object1, Object object2); + + TypeInfo[] UNOTYPEINFO = { + new MethodTypeInfo("notifyAccepting", 0, TypeInfo.ONEWAY) }; + } + + // Use "127.0.0.1" instead of "localhost", see #i32281#: + private static final String CONNECTION_DESCRIPTION + = "socket,host=127.0.0.1,port=12346"; + private static final String PROTOCOL_DESCRIPTION = "urp"; + + private static final String INSTANCE1 = "instance1"; + private static final String INSTANCE2 = "instance2"; +} diff --git a/bridges/test/java_uno/equals/makefile.mk b/bridges/test/java_uno/equals/makefile.mk new file mode 100644 index 000000000000..9ac266f80ff5 --- /dev/null +++ b/bridges/test/java_uno/equals/makefile.mk @@ -0,0 +1,96 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +PRJNAME = bridges + +TARGET = test_javauno_equals +PACKAGE = test$/java_uno$/equals + +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk + +# Make sure TestBed.class is found under $(CLASSDIR)$/test: +.IF "$(XCLASSPATH)" == "" +XCLASSPATH := $(CLASSDIR)$/test +.ELSE +XCLASSPATH !:= $(XCLASSPATH)$(PATH_SEPERATOR)$(CLASSDIR)$/test +.ENDIF + +DLLPRE = # no leading "lib" on .so files +INCPRE += $(MISC)$/$(TARGET)$/inc + +SLOFILES = $(SLO)$/testequals.obj + +SHL1TARGET = testequals.uno +SHL1OBJS = $(SLOFILES) +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1IMPLIB = itestequals + +JAVAFILES = TestEquals.java +JARFILES = juh.jar jurt.jar ridl.jar + +.INCLUDE: target.mk + +ALLTAR: $(BIN)$/testequals + +.IF "$(GUI)" == "WNT" +GIVE_EXEC_RIGHTS = @echo +.ELSE # GUI, WNT +GIVE_EXEC_RIGHTS = chmod +x +.ENDIF # GUI, WNT + +EXEC_CLASSPATH_TMP = $(foreach,i,$(JARFILES) $(SOLARBINDIR)$/$i) +EXEC_CLASSPATH = \ + $(strip $(subst,!,$(PATH_SEPERATOR) $(EXEC_CLASSPATH_TMP:s/ /!/))) + +$(MISC)$/$(TARGET).rdb: types.idl + - rm $@ + - $(MKDIR) $(MISC)$/$(TARGET) + - $(MKDIR) $(MISC)$/$(TARGET)$/inc + $(IDLC) -I$(SOLARIDLDIR) -O$(MISC)$/$(TARGET) $< + $(REGMERGE) $(MISC)$/$(TARGET).rdb /UCR $(MISC)$/$(TARGET)$/types.urd + $(CPPUMAKER) -BUCR -C -O$(MISC)$/$(TARGET)$/inc $@ -X$(SOLARBINDIR)$/types.rdb + $(JAVAMAKER) -BUCR -nD -O$(CLASSDIR) $@ -X$(SOLARBINDIR)$/types.rdb + +$(SLOFILES) $(JAVACLASSFILES): $(MISC)$/$(TARGET).rdb + +$(BIN)$/testequals: $(BIN)$/testequals_services.rdb + echo '$(AUGMENT_LIBRARY_PATH)' java -classpath \ + ..$/class$/test$(PATH_SEPERATOR)..$/class$(PATH_SEPERATOR)\ +..$/class$/java_uno.jar$(PATH_SEPERATOR)$(EXEC_CLASSPATH) \ + test.java_uno.equals.TestEquals $(SOLARBINDIR)$/types.rdb \ + testequals_services.rdb > $@ + $(GIVE_EXEC_RIGHTS) $@ + +$(BIN)$/testequals_services.rdb: + - rm $@ + $(REGCOMP) -register -r $@ -c bridgefac.uno + $(REGCOMP) -register -r $@ -c connector.uno + $(REGCOMP) -register -r $@ -c remotebridge.uno diff --git a/bridges/test/java_uno/equals/testequals.cxx b/bridges/test/java_uno/equals/testequals.cxx new file mode 100644 index 000000000000..7e4aa754fcda --- /dev/null +++ b/bridges/test/java_uno/equals/testequals.cxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "com/sun/star/bridge/XBridge.hpp" +#include "com/sun/star/bridge/XBridgeFactory.hpp" +#include "com/sun/star/connection/Connector.hpp" +#include "com/sun/star/connection/XConnection.hpp" +#include "com/sun/star/connection/XConnector.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/string.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "test/java_uno/equals/XBase.hpp" +#include "test/java_uno/equals/XDerived.hpp" +#include "test/java_uno/equals/XTestInterface.hpp" +#include "uno/environment.h" +#include "uno/lbnames.h" + +namespace css = com::sun::star; + +namespace { + +class Service: public cppu::WeakImplHelper2< + css::lang::XServiceInfo, test::java_uno::equals::XTestInterface > +{ +public: + virtual inline rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return rtl::OUString::createFromAscii(getImplementationName_static()); } + + virtual sal_Bool SAL_CALL supportsService( + rtl::OUString const & rServiceName) throw (css::uno::RuntimeException); + + virtual inline css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return getSupportedServiceNames_static(); } + + virtual void SAL_CALL connect(rtl::OUString const & rConnection, + rtl::OUString const & rProtocol) + throw (css::uno::Exception); + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL get( + rtl::OUString const & rName) throw (css::uno::RuntimeException); + + static inline sal_Char const * getImplementationName_static() + { return "com.sun.star.test.bridges.testequals.impl"; } + + static css::uno::Sequence< rtl::OUString > + getSupportedServiceNames_static(); + + static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( + css::uno::Reference< css::uno::XComponentContext > const & rContext) + throw (css::uno::Exception); + +private: + explicit inline Service( + css::uno::Reference< css::uno::XComponentContext > const & rContext): + m_xContext(rContext) {} + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::bridge::XBridge > m_xBridge; +}; + +} + +sal_Bool Service::supportsService(rtl::OUString const & rServiceName) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< rtl::OUString > aNames( + getSupportedServiceNames_static()); + for (sal_Int32 i = 0; i< aNames.getLength(); ++i) + if (aNames[i] == rServiceName) + return true; + return false; +} + +void Service::connect(rtl::OUString const & rConnection, + rtl::OUString const & rProtocol) + throw (css::uno::Exception) +{ + css::uno::Reference< css::connection::XConnection > xConnection( + css::connection::Connector::create(m_xContext)->connect(rConnection)); + css::uno::Reference< css::bridge::XBridgeFactory > xBridgeFactory( + m_xContext->getServiceManager()->createInstanceWithContext( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.bridge.BridgeFactory" )), + m_xContext), + css::uno::UNO_QUERY); + m_xBridge = xBridgeFactory->createBridge(rtl::OUString(), rProtocol, + xConnection, 0); +} + +css::uno::Reference< css::uno::XInterface > +Service::get(rtl::OUString const & rName) throw (css::uno::RuntimeException) +{ + return m_xBridge->getInstance(rName); +} + +css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames_static() +{ + css::uno::Sequence< rtl::OUString > aNames(1); + aNames[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.test.bridges.testequals" )); + return aNames; +} + +css::uno::Reference< css::uno::XInterface > Service::createInstance( + css::uno::Reference< css::uno::XComponentContext > const & rContext) + throw (css::uno::Exception) +{ + // Make types known: + getCppuType( + static_cast< + css::uno::Reference< test::java_uno::equals::XBase > const * >(0)); + getCppuType( + static_cast< + css::uno::Reference< test::java_uno::equals::XDerived > const * >(0)); + getCppuType( + static_cast< + css::uno::Reference< test::java_uno::equals::XTestInterface > const * >( + 0)); + + return static_cast< cppu::OWeakObject * >(new Service(rContext)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(sal_Char const * pImplName, + void * pServiceManager, void *) +{ + void * pFactory = 0; + if (pServiceManager) + if (rtl_str_compare(pImplName, Service::getImplementationName_static()) + == 0) + { + css::uno::Reference< css::lang::XSingleComponentFactory > + xFactory(cppu::createSingleComponentFactory( + &Service::createInstance, + rtl::OUString::createFromAscii( + Service::getImplementationName_static()), + Service::getSupportedServiceNames_static())); + if (xFactory.is()) + { + xFactory->acquire(); + pFactory = xFactory.get(); + } + } + return pFactory; +} + +namespace { + +bool writeInfo(void * pRegistryKey, sal_Char const * pImplementationName, + css::uno::Sequence< rtl::OUString > const & rServiceNames) +{ + rtl::OUString aKeyName( RTL_CONSTASCII_USTRINGPARAM( "/" )); + aKeyName += rtl::OUString::createFromAscii(pImplementationName); + aKeyName += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES" )); + css::uno::Reference< css::registry::XRegistryKey > xKey; + try + { + xKey = static_cast< css::registry::XRegistryKey * >(pRegistryKey)-> + createKey(aKeyName); + } + catch (css::registry::InvalidRegistryException &) {} + if (!xKey.is()) + return false; + bool bSuccess = true; + for (sal_Int32 i = 0; i < rServiceNames.getLength(); ++i) + try + { + xKey->createKey(rServiceNames[i]); + } + catch (css::registry::InvalidRegistryException &) + { + bSuccess = false; + break; + } + return bSuccess; +} + +} + +extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * pRegistryKey) +{ + return pRegistryKey + && writeInfo(pRegistryKey, Service::getImplementationName_static(), + Service::getSupportedServiceNames_static()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/java_uno/equals/types.idl b/bridges/test/java_uno/equals/types.idl new file mode 100644 index 000000000000..c8ddc2f072fe --- /dev/null +++ b/bridges/test/java_uno/equals/types.idl @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "com/sun/star/uno/Exception.idl" +#include "com/sun/star/uno/XInterface.idl" + +// UNO interfaces used between Java and native (C++) environments. + +module test { module java_uno { module equals { + +interface XBase: com::sun::star::uno::XInterface {}; + +interface XDerived: XBase {}; + +interface XTestInterface: com::sun::star::uno::XInterface +{ + void connect([in] string connection, [in] string protocol) + raises (com::sun::star::uno::Exception); + + com::sun::star::uno::XInterface get([in] string name); +}; + +}; }; }; diff --git a/bridges/test/java_uno/nativethreadpool/Relay.java b/bridges/test/java_uno/nativethreadpool/Relay.java new file mode 100644 index 000000000000..50e198a2d819 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/Relay.java @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package test.javauno.nativethreadpool; + +import com.sun.star.bridge.BridgeExistsException; +import com.sun.star.bridge.XBridgeFactory; +import com.sun.star.bridge.XInstanceProvider; +import com.sun.star.comp.helper.Bootstrap; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.connection.AlreadyAcceptingException; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.connection.Acceptor; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.lang.WrappedTargetRuntimeException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +public final class Relay implements XRelay, XSource { + public void start(XSource source) { + this.source = source; + XComponentContext context; + try { + context = Bootstrap.createInitialComponentContext(null); + } catch (RuntimeException e) { + throw e; + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetRuntimeException(e.toString(), this, e); + } catch (Exception e) { + throw new com.sun.star.uno.RuntimeException(e.toString(), this); + } + final XAcceptor acceptor = Acceptor.create(context); + final XBridgeFactory factory; + try { + factory = UnoRuntime.queryInterface( + XBridgeFactory.class, + context.getServiceManager().createInstanceWithContext( + "com.sun.star.bridge.BridgeFactory", context)); + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetRuntimeException(e.toString(), this, e); + } + new Thread() { + public void run() { + try { + // Use "127.0.0.1" instead of "localhost", see #i32281#: + factory.createBridge( + "", "urp", + acceptor.accept("socket,host=127.0.0.1,port=3831"), + new XInstanceProvider() { + public Object getInstance(String instanceName) { + return Relay.this; + } + }); + } catch (AlreadyAcceptingException e) { + e.printStackTrace(System.err); + } catch (ConnectionSetupException e) { + e.printStackTrace(System.err); + } catch (BridgeExistsException e) { + e.printStackTrace(System.err); + } catch (com.sun.star.lang.IllegalArgumentException e) { + e.printStackTrace(System.err); + } + } + }.start(); + try { + Thread.sleep(3000); // wait for new thread to accept connection + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new com.sun.star.uno.RuntimeException(e.toString(), this); + } + } + + public int get() { + return source.get(); + } + + public static XSingleServiceFactory __getServiceFactory( + String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + return implName.equals(implementationName) + ? FactoryHelper.getServiceFactory( + Relay.class, serviceName, multiFactory, regKey) + : null; + } + + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return FactoryHelper.writeRegistryServiceInfo( + implementationName, serviceName, regKey); + } + + private static final String implementationName + = "test.javauno.nativethreadpool.comp.Relay"; + private static final String serviceName + = "test.javauno.nativethreadpool.Relay"; + + private XSource source; +} diff --git a/bridges/test/java_uno/nativethreadpool/makefile.mk b/bridges/test/java_uno/nativethreadpool/makefile.mk new file mode 100644 index 000000000000..d4926e07307b --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/makefile.mk @@ -0,0 +1,121 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ := ..$/..$/.. +PRJNAME := bridges + +TARGET := test_javauno_nativethreadpool +PACKAGE := test$/javauno$/nativethreadpool + +ENABLE_EXCEPTIONS := TRUE + +#TODO: +.IF "$(OS)" == "LINUX" +JVM_LIB_URL := file:///net/grande.germany/develop6/update/dev/Linux_JDK_1.4.1_03/jre/lib/i386/client/libjvm.so +.ELSE +ERROR -- missing platform +.ENDIF + +.INCLUDE: settings.mk + +DLLPRE = # no leading "lib" on .so files +INCPRE += $(MISC)$/$(TARGET)$/inc + +SHL1TARGET = $(TARGET)_client.uno +SHL1OBJS = $(SLO)$/testnativethreadpoolclient.obj +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(TARGET)_client + +SHL2TARGET = $(TARGET)_server.uno +SHL2OBJS = $(SLO)$/testnativethreadpoolserver.obj +SHL2STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL2VERSIONMAP = version.map +SHL2IMPLIB = i$(TARGET)_server + +SLOFILES = $(SHL1OBJS) $(SHL2OBJS) + +JAVAFILES = Relay.java +JARFILES = java_uno.jar juh.jar jurt.jar ridl.jar + +.INCLUDE: target.mk + +ALLTAR: test + +EXEC_CLASSPATH_TMP = $(foreach,i,$(JARFILES) $(SOLARBINDIR)$/$i) +EXEC_CLASSPATH = \ + $(strip $(subst,!,$(PATH_SEPERATOR) $(EXEC_CLASSPATH_TMP:s/ /!/))) + +$(MISC)$/$(TARGET)$/types.rdb: types.idl + - rm $@ + - $(MKDIR) $(MISC)$/$(TARGET) + - $(MKDIR) $(MISC)$/$(TARGET)$/inc + $(IDLC) -I$(SOLARIDLDIR) -O$(MISC)$/$(TARGET) $< + $(REGMERGE) $@ /UCR $(MISC)$/$(TARGET)$/types.urd + $(CPPUMAKER) -BUCR -C -O$(MISC)$/$(TARGET)$/inc $@ -X$(SOLARBINDIR)$/types.rdb + $(JAVAMAKER) -BUCR -nD -O$(CLASSDIR) $@ -X$(SOLARBINDIR)$/types.rdb + +$(SLOFILES) $(JAVACLASSFILES): $(MISC)$/$(TARGET)$/types.rdb + +$(BIN)$/$(TARGET).uno.jar: $(JAVACLASSFILES) relay.manifest + jar cfm $@ relay.manifest -C $(CLASSDIR) test/javauno/nativethreadpool + +$(BIN)$/$(TARGET).rdb .ERRREMOVE: $(MISC)$/$(TARGET)$/types.rdb \ + $(BIN)$/$(TARGET).uno.jar + cp $(MISC)$/$(TARGET)$/types.rdb $@ + $(REGMERGE) $@ / $(SOLARBINDIR)$/types.rdb + $(REGCOMP) -register -r $@ -c acceptor.uno$(DLLPOST) \ + -c bridgefac.uno$(DLLPOST) -c connector.uno$(DLLPOST) \ + -c remotebridge.uno$(DLLPOST) -c uuresolver.uno$(DLLPOST) \ + -c javaloader.uno$(DLLPOST) -c javavm.uno$(DLLPOST) \ + -c stocservices.uno$(DLLPOST) + cp $(SOLARBINDIR)$/types.rdb $(MISC)$/$(TARGET)$/bootstrap.rdb + $(REGCOMP) -register -r $(MISC)$/$(TARGET)$/bootstrap.rdb \ + -c javaloader.uno$(DLLPOST) -c javavm.uno$(DLLPOST) \ + -c stocservices.uno$(DLLPOST) +.IF "$(GUI)" == "WNT" + ERROR -- missing platform +.ELSE # GUI, WNT + + export OO_JAVA_PROPERTIES='RuntimeLib=$(JVM_LIB_URL)' && \ + $(REGCOMP) -register -r $@ -c file://$(PWD)/$(BIN)$/$(TARGET).uno.jar \ + -br $(MISC)$/$(TARGET)$/bootstrap.rdb -classpath $(EXEC_CLASSPATH) \ + -env:URE_INTERNAL_JAVA_DIR=file://$(SOLARBINDIR) +.ENDIF # GUI, WNT + +test .PHONY: $(SHL1TARGETN) $(BIN)$/$(TARGET).uno.jar $(BIN)$/$(TARGET).rdb +.IF "$(GUI)" == "WNT" + ERROR -- missing platform +.ELSE # GUI, WNT + $(AUGMENT_LIBRARY_PATH) uno -c test.javauno.nativethreadpool.server \ + -l $(SHL2TARGETN) -ro $(BIN)$/$(TARGET).rdb \ + -u 'uno:socket,host=localhost,port=3830;urp;test' --singleaccept & + + $(AUGMENT_LIBRARY_PATH) OO_JAVA_PROPERTIES='RuntimeLib=$(JVM_LIB_URL)' \ + CLASSPATH=$(EXEC_CLASSPATH)$(PATH_SEPERATOR)$(BIN)$/$(TARGET).uno.jar \ + uno -c test.javauno.nativethreadpool.client -l $(SHL1TARGETN) \ + -ro $(BIN)$/$(TARGET).rdb \ + -env:URE_INTERNAL_JAVA_DIR=file://$(SOLARBINDIR) +.ENDIF # GUI, WNT diff --git a/bridges/test/java_uno/nativethreadpool/readme b/bridges/test/java_uno/nativethreadpool/readme new file mode 100644 index 000000000000..c137ed162372 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/readme @@ -0,0 +1,39 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +Test that a Java URP bridge started in a native process uses the same thread +pool as a C++ URP bridge. This test currently only works on Linux Intel. + +There are two processes involved. The client starts as a native process. It +first loads a Java component (Relay) via the in-process JNI bridge, which in +turn starts to accept incomming URP connections. The native part of the client +then connects to the server, retrieves a thread-local token from it, and checks +the token for correctness. The server simply waits for a connection from the +native part of the client, creates a connection to the Java part of the client, +and routes all requests from the native part of the client to the Java part of +the client. The Java part of the client in turn uses the in-process JNI bridge +to obtain the thread-local token. diff --git a/bridges/test/java_uno/nativethreadpool/relay.manifest b/bridges/test/java_uno/nativethreadpool/relay.manifest new file mode 100644 index 000000000000..6cd1d9dbd611 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/relay.manifest @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +RegistrationClassName: test.javauno.nativethreadpool.Relay diff --git a/bridges/test/java_uno/nativethreadpool/testnativethreadpoolclient.cxx b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolclient.cxx new file mode 100644 index 000000000000..82737af756f6 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolclient.cxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "test/javauno/nativethreadpool/XRelay.hpp" +#include "test/javauno/nativethreadpool/XSource.hpp" + +#include "com/sun/star/bridge/UnoUrlResolver.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/connection/ConnectionSetupException.hpp" +#include "com/sun/star/connection/NoConnectException.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/thread.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" + +#include <iostream> + +namespace css = com::sun::star; + +namespace { + +class Client: public cppu::WeakImplHelper2< + css::lang::XMain, test::javauno::nativethreadpool::XSource > +{ +public: + explicit Client( + css::uno::Reference< css::uno::XComponentContext > const & theContext): + context(theContext) {} + +private: + virtual ~Client() {} + + virtual sal_Int32 SAL_CALL run(css::uno::Sequence< rtl::OUString > const &) + throw (css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL get() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context; + osl::ThreadData data; +}; + +sal_Int32 Client::run(css::uno::Sequence< rtl::OUString > const &) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > factory( + context->getServiceManager()); + if (!factory.is()) { + throw new css::uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no component context service manager" )), + static_cast< cppu::OWeakObject * >(this)); + } + css::uno::Reference< test::javauno::nativethreadpool::XRelay > relay; + try { + relay = css::uno::Reference< test::javauno::nativethreadpool::XRelay >( + factory->createInstanceWithContext( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "test.javauno.nativethreadpool.Relay" )), + context), + css::uno::UNO_QUERY_THROW); + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::uno::Exception & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "creating test.javauno.nativethreadpool.Relay service" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } + relay->start(this); + if (!data.setData(reinterpret_cast< void * >(12345))) { + throw new css::uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "osl::ThreadData::setData failed" )), + static_cast< cppu::OWeakObject * >(this)); + } + css::uno::Reference< test::javauno::nativethreadpool::XSource > source; + try { + source + = css::uno::Reference< test::javauno::nativethreadpool::XSource >( + css::bridge::UnoUrlResolver::create(context)->resolve( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "uno:socket,host=localhost,port=3830;urp;test" ))), + css::uno::UNO_QUERY_THROW); + } catch (css::connection::NoConnectException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } catch (css::connection::ConnectionSetupException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } catch (css::lang::IllegalArgumentException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } + bool success = source->get() == 12345; + std::cout << "success? " << (success ? "yes" : "no") << '\n'; + return success ? 0 : 1; +} + +sal_Int32 Client::get() throw (css::uno::RuntimeException) { + return reinterpret_cast< sal_Int32 >(data.getData()); +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL create( + css::uno::Reference< css::uno::XComponentContext > const & context) + SAL_THROW((css::uno::Exception)) +{ + return static_cast< cppu::OWeakObject * >(new Client(context)); +} + +rtl::OUString SAL_CALL getImplementationName() { + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "test.javauno.nativethreadpool.client" )); +} + +css::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +cppu::ImplementationEntry entries[] = { + { &create, &getImplementationName, &getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx new file mode 100644 index 000000000000..b22dc8dfeb48 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include "test/javauno/nativethreadpool/XSource.hpp" + +#include "com/sun/star/bridge/UnoUrlResolver.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/connection/ConnectionSetupException.hpp" +#include "com/sun/star/connection/NoConnectException.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" + +namespace css = com::sun::star; + +namespace { + +class Server: + public cppu::WeakImplHelper1< test::javauno::nativethreadpool::XSource > +{ +public: + explicit Server( + css::uno::Reference< css::uno::XComponentContext > const & theContext): + context(theContext) {} + +private: + virtual ~Server() {} + + virtual sal_Int32 SAL_CALL get() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context; +}; + +sal_Int32 Server::get() throw (css::uno::RuntimeException) { + css::uno::Reference< css::lang::XMultiComponentFactory > factory( + context->getServiceManager()); + if (!factory.is()) { + throw new css::uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no component context service manager" )), + static_cast< cppu::OWeakObject * >(this)); + } + css::uno::Reference< test::javauno::nativethreadpool::XSource > source; + try { + // Use "127.0.0.1" instead of "localhost", see #i32281#: + source + = css::uno::Reference< test::javauno::nativethreadpool::XSource >( + css::bridge::UnoUrlResolver::create(context)->resolve( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "uno:socket,host=127.0.0.1,port=3831;urp;test" ))), + css::uno::UNO_QUERY_THROW); + } catch (css::connection::NoConnectException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } catch (css::connection::ConnectionSetupException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } catch (css::lang::IllegalArgumentException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.UnoUrlResolver.resolve" )), + static_cast< cppu::OWeakObject * >(this), css::uno::makeAny(e)); + } + return source->get(); +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL create( + css::uno::Reference< css::uno::XComponentContext > const & context) + SAL_THROW((css::uno::Exception)) +{ + return static_cast< cppu::OWeakObject * >(new Server(context)); +} + +rtl::OUString SAL_CALL getImplementationName() { + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "test.javauno.nativethreadpool.server" )); +} + +css::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +cppu::ImplementationEntry entries[] = { + { &create, &getImplementationName, &getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/java_uno/nativethreadpool/types.idl b/bridges/test/java_uno/nativethreadpool/types.idl new file mode 100644 index 000000000000..36ca44af37e0 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/types.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "com/sun/star/uno/XInterface.idl" + +module test { module javauno { module nativethreadpool { + +interface XSource: com::sun::star::uno::XInterface { + long get(); +}; + +interface XRelay: com::sun::star::uno::XInterface { + void start([in] XSource source); +}; + +}; }; }; diff --git a/bridges/test/java_uno/nativethreadpool/version.map b/bridges/test/java_uno/nativethreadpool/version.map new file mode 100644 index 000000000000..c24529e13509 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/version.map @@ -0,0 +1,33 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +UDK_3_0_0 { + global: + component_getFactory; + local: + *; +}; diff --git a/bridges/test/makefile.mk b/bridges/test/makefile.mk new file mode 100644 index 000000000000..1c8c6f8cf10d --- /dev/null +++ b/bridges/test/makefile.mk @@ -0,0 +1,175 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. + +PRJNAME=bridges +TARGET=test +LIBTARGET=NO +TARGETTYPE=CUI +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +ALLIDLFILES = test_bridge.idl +CPPUMAKERFLAGS += -C + + +UNOUCRDEP=$(SOLARBINDIR)$/udkapi.rdb $(BIN)$/test.rdb +UNOUCRRDB=$(SOLARBINDIR)$/udkapi.rdb $(BIN)$/test.rdb + +# output directory (one dir for each project) +UNOUCROUT=$(OUT)$/inc + +# adding to inludeoath +INCPRE+=$(UNOUCROUT) +CFLAGS += -I..$/source$/remote$/urp + +UNOTYPES = \ + com.sun.star.uno.XWeak\ + com.sun.star.uno.XNamingService\ + com.sun.star.uno.XAggregation \ + com.sun.star.uno.TypeClass\ + com.sun.star.io.XInputStream\ + com.sun.star.io.XOutputStream\ + com.sun.star.lang.XInitialization \ + com.sun.star.lang.XSingleServiceFactory \ + com.sun.star.lang.XMultiServiceFactory \ + com.sun.star.lang.XTypeProvider \ + com.sun.star.registry.XSimpleRegistry \ + com.sun.star.loader.XImplementationLoader \ + com.sun.star.registry.XImplementationRegistration \ + com.sun.star.corba.giop.TargetAddress \ + com.sun.star.corba.giop.TargetAddressGroup \ + com.sun.star.lang.XComponent \ + com.sun.star.bridge.XBridgeFactory\ + com.sun.star.connection.XAcceptor\ + com.sun.star.connection.XConnector\ + com.sun.star.beans.Property\ + com.sun.star.corba.giop.RequestHeader_1_2\ + com.sun.star.container.XSet\ + com.sun.star.lang.XServiceInfo\ + test.XTestFactory \ + com.sun.star.test.performance.XPerformanceTest \ + com.sun.star.lang.XMain \ + com.sun.star.lang.XMultiComponentFactory \ + com.sun.star.lang.XSingleComponentFactory + +JARFILES = jurt.jar unoil.jar + +OBJFILES= \ + $(OBJ)$/testserver.obj \ + $(OBJ)$/testclient.obj \ + $(OBJ)$/testcomp.obj \ + $(OBJ)$/testsameprocess.obj + + +APP2TARGET= testserver +APP2OBJS= $(OBJ)$/testserver.obj \ + $(OBJ)$/testcomp.obj + +.IF "$(OS)" == "LINUX" +APP2STDLIBS+= -lstdc++ +.ENDIF + +APP2STDLIBS+= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +APP3TARGET= testclient +APP3OBJS= $(OBJ)$/testclient.obj \ + $(OBJ)$/testcomp.obj + +.IF "$(OS)" == "LINUX" +APP3STDLIBS+= -lstdc++ +.ENDIF + +APP3STDLIBS+= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +#---------------------------------- + +APP4TARGET= testsameprocess +APP4OBJS= $(OBJ)$/testsameprocess.obj \ + $(OBJ)$/testcomp.obj + +.IF "$(OS)" == "LINUX" +APP4STDLIBS+= -lstdc++ +.ENDIF + +APP4STDLIBS+= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +APP4DEF= $(MISC)$/$(APP4TARGET).def + +#---------------------------------- + +# APP5TARGET= testoffice +# APP5OBJS= $(OBJ)$/testoffice.obj \ +# $(OBJ)$/testcomp.obj + +# .IF "$(OS)" == "LINUX" +# APP5STDLIBS+= -lstdc++ +# .ENDIF + +# APP5STDLIBS+= \ +# $(CPPULIB) \ +# $(CPPUHELPERLIB)\ +# $(SALLIB) + +# APP5DEF= $(MISC)$/$(APP5TARGET).def + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(BIN)$/test.rdb \ + $(BIN)$/server.rdb \ + $(BIN)$/client.rdb + +$(BIN)$/test.rdb: $(ALLIDLFILES) + $(IDLC) -I$(PRJ) -I$(SOLARIDLDIR) -O$(BIN) $? + $(REGMERGE) $@ /UCR $(BIN)$/{$(?:f:s/.idl/.urd/)} + touch $@ + +$(BIN)$/client.rdb: $(BIN)$/test.rdb + rm -f $(BIN)$/client.rdb + $(REGMERGE) $@ / $(BIN)$/test.rdb $(SOLARBINDIR)$/udkapi.rdb + +$(BIN)$/server.rdb: $(BIN)$/test.rdb + rm -f $(BIN)$/client.rdb + $(REGMERGE) $@ / $(BIN)$/test.rdb $(SOLARBINDIR)$/udkapi.rdb + diff --git a/bridges/test/performance/makefile.mk b/bridges/test/performance/makefile.mk new file mode 100644 index 000000000000..44f7ae3d4414 --- /dev/null +++ b/bridges/test/performance/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=bridges +TARGET=test +LIBTARGET=NO +TARGETTYPE=CUI +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= $(OBJ)$/testperformance.obj + +#---------------------------------- + +APP1TARGET= testperformance +APP1OBJS= $(OBJ)$/testperformance.obj + +.IF "$(OS)" == "LINUX" +APP1STDLIBS+= -lstdc++ +.ENDIF + +APP1STDLIBS+= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +APP1DEF= $(MISC)$/$(APP1TARGET).def + +.INCLUDE : target.mk + diff --git a/bridges/test/performance/testperformance.cxx b/bridges/test/performance/testperformance.cxx new file mode 100644 index 000000000000..d692144a3f37 --- /dev/null +++ b/bridges/test/performance/testperformance.cxx @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <stdio.h> +#include <math.h> + +#include <osl/interlck.h> +#include <osl/mutex.hxx> +#include <osl/semaphor.h> + +#include <rtl/string.hxx> +#include <rtl/byteseq.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +#ifdef SAL_W32 +#include <windows.h> +#else +#include <sys/times.h> +#endif +#ifndef ULONG_MAX +#define ULONG_MAX 0xffffffff +#endif + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; + +static inline sal_uInt32 getSystemTicks() +{ +#ifdef SAL_W32 + return (sal_uInt32)GetTickCount(); +#else // only UNX supported for now + static sal_uInt32 nImplTicksPerSecond = 0; + static double dImplTicksPerSecond; + static double dImplTicksULONGMAX; + + struct tms aTms; + sal_uInt32 nTicks = (sal_uInt32)times( &aTms ); + + if ( !nImplTicksPerSecond ) + { + nImplTicksPerSecond = CLK_TCK; + dImplTicksPerSecond = nImplTicksPerSecond; + dImplTicksULONGMAX = (double)(sal_uInt32)ULONG_MAX; + } + + double fTicks = nTicks; + fTicks *= 1000; + fTicks /= dImplTicksPerSecond; + fTicks = fmod (fTicks, dImplTicksULONGMAX); + + return (sal_uInt32)fTicks; +#endif +} + +class MyTimer +{ +public: + MyTimer( const OString &descString ) : + nStart( getSystemTicks() ), + m_descString( descString ) + { + } + ~MyTimer( ) + { + printf( "%f s : %s\n", (getSystemTicks() -nStart) / 1000., m_descString.getStr() ); + } +private: + sal_uInt32 nStart; + OString m_descString; +}; + +void main() +{ + // interlocked count + { + MyTimer timer( "performance - 1000*10000 interlocked count" ); + oslInterlockedCount count; + for( int i = 0 ; i < 1000*10000 ; i ++ ) + { + osl_incrementInterlockedCount( &count ); + } + } + { + OString myDummyString( "blubber" ); + MyTimer timer( "performance - 1000*10000 acquiring/releasing a refcounted string(without destruction)" ); + for( int i = 0 ; i < 1000*10000 ; i ++ ) + { + OString myNextDummyString = myDummyString ; + } + } + + printf( "--------------------\n" ); + { + Mutex mutex; + MyTimer timer( "performance - 1000*10000 acquiring/releasing an osl::Mutex" ); + for( int i = 0 ; i < 1000*10000 ; i ++ ) + { + MutexGuard guard( mutex ); + } + } + + { + oslSemaphore sema = osl_createSemaphore(1); + MyTimer timer( "performance - 1000*10000 acquiring/releasing an osl::Semaphore" ); + for( int i = 0 ; i < 1000*10000 ; i ++ ) + { + osl_acquireSemaphore( sema ); + osl_releaseSemaphore( sema ); + } + } + + printf( "--------------------\n" ); + { + MyTimer timer( "performance - 1000*10000 rtl::ByteSequence(500)" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + ByteSequence seq(500); + } + } + + { + MyTimer timer( "performance - 1000*1000 rtl::ByteSequence(500,BYTESEQ_NODEFAULT)" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + ByteSequence seq(500, BYTESEQ_NODEFAULT); + } + } + { + MyTimer timer( "performance - 1000*1000 com::sun::star::uno::Sequence< sal_Int8 > (500)" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + Sequence< sal_Int8> seq(500); + } + } + { + MyTimer timer( "performance - 1000*1000 rtl_freeMemory( rtl_allocateMemory( 512 ) )" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + rtl_freeMemory( rtl_allocateMemory( 512 ) ); + } + } + + printf( "--------------------\n" ); + { + MyTimer timer( "performance - 1000*1000 byte string construction/destruction" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + OString textEnc( "this is a test string" ); + } + } + + { + MyTimer timer( "performance - 1000*1000 unicode string construction/destruction" ); + for( int i = 0 ; i < 1000*1000 ; i ++ ) + { + OUString textEnc( RTL_CONSTASCII_USTRINGPARAM( "this is a test string" ) ); + } + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/test_bridge.idl b/bridges/test/test_bridge.idl new file mode 100644 index 000000000000..ce38594ecd88 --- /dev/null +++ b/bridges/test/test_bridge.idl @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <com/sun/star/uno/XInterface.idl> +#include <com/sun/star/uno/Exception.idl> + +module test +{ + +struct TestTypes +{ + boolean Bool; + char Char; + byte Byte; + short Short; + unsigned short UShort; + long Long; + unsigned long ULong; + hyper Hyper; + unsigned hyper UHyper; + float Float; + double Double; +// test::TestEnum Enum; + string String; + com::sun::star::uno::XInterface Interface; + any Any; +}; + +exception TestBridgeException : com::sun::star::uno::Exception +{ + +}; + +interface XCallMe : com::sun::star::uno::XInterface +{ + void call( [in] string s , [in] long nToDo ) raises( TestBridgeException ); + [oneway] void callOneway( [in] string s , [in] long nToDo ); + [attribute] string sAttribute; + void callAgain( [in] XCallMe callAgain, [in] long nToCall ); + TestTypes transport( [in] TestTypes types ); + [oneway] void drawLine( [in] long x1 , [in] long y1, [in] long x2, [in] long y2 ); +}; + +interface XInterfaceTest : com::sun::star::uno::XInterface +{ + void setIn( [in] XCallMe callback ); + void setInOut( [inout] XCallMe callback ); + void getOut( [out] XCallMe callback ); + XCallMe get(); +}; + +interface XTestFactory : com::sun::star::uno::XInterface +{ + XCallMe createCallMe(); + XInterfaceTest createInterfaceTest(); +}; + + +}; diff --git a/bridges/test/testclient.cxx b/bridges/test/testclient.cxx new file mode 100644 index 000000000000..be5223fb5873 --- /dev/null +++ b/bridges/test/testclient.cxx @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <string.h> + +#include <osl/time.h> + +#include <osl/mutex.hxx> +#include <osl/module.h> +#include <osl/thread.h> +#include <osl/conditn.h> +#include <osl/diagnose.h> + +#include <uno/mapping.hxx> + +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/connection/XConnector.hpp> + +#include <com/sun/star/bridge/XBridgeFactory.hpp> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMain.hpp> + +#include <com/sun/star/test/performance/XPerformanceTest.hpp> + +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> + +#include <test/XTestFactory.hpp> + + +using namespace ::test; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::connection; +using namespace ::com::sun::star::test::performance; + +#include "testcomp.h" + + +void doPerformanceTest( const Reference < XPerformanceTest > & /* xBench */) +{ + printf( "not implemented\n" ); +// sal_Int32 i,nLoop = 2000; +// sal_Int32 tStart, tEnd , tEnd2; +// //------------------------------------ +// // oneway calls +// i = nLoop; +// tStart = GetTickCount(); +// while (i--) +// xBench->async(); +// tEnd = GetTickCount(); +// xBench->sync(); +// tEnd2 = GetTickCount(); +// printf( "%d %d %d\n" , nLoop, tEnd - tStart , tEnd2 -tStart ); +// // synchron calls +// i = nLoop; +// tStart = GetTickCount(); +// while (i--) +// xBench->sync(); +// tEnd = GetTickCount(); +// printf( "%d %d \n" , nLoop, tEnd - tStart ); + +} + +void testLatency( const Reference < XConnection > &r , sal_Bool /* bReply */) +{ + sal_Int32 nLoop = 10000; + TimeValue aStartTime, aEndTime; + osl_getSystemTime( &aStartTime ); + + sal_Int32 i; + for( i = 0 ; i < nLoop ; i++ ) + { + Sequence< sal_Int8 > s1( 200 ); + r->write( s1 ); + r->read( s1 , 12 ); + r->read( s1 , 48 ); + } + osl_getSystemTime( &aEndTime ); + + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + + printf( "System latency per call : %g\n" , (( fEnd-fStart )/2.) / ((double)(nLoop)) ); +} + +int main( int argc, char *argv[] ) +{ + if( argc < 2 ) + { + printf( + "usage : testclient [-r] connectionstring\n" + " -r reverse call me test (server calls client)" + ); + return 0; + } + + OUString sConnectionString; + OUString sProtocol; + sal_Bool bLatency = sal_False; + sal_Bool bReverse = sal_False; + + parseCommandLine( argv , &sConnectionString , &sProtocol , &bLatency , &bReverse ); + + { + Reference< XMultiServiceFactory > rSMgr = createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM("client.rdb")) ); + + + Reference < XConnector > rConnector( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Connector")), + OUString( RTL_CONSTASCII_USTRINGPARAM("connector.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + + try + { + Reference < XConnection > rConnection = + rConnector->connect( sConnectionString ); + + printf( "%s\n" , OUStringToOString( rConnection->getDescription(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + + + if( bLatency ) + { + testLatency( rConnection , sal_False ); + testLatency( rConnection , sal_True ); + } + else + { + // just ensure that it is registered + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.Bridge.iiop")), + OUString( RTL_CONSTASCII_USTRINGPARAM("remotebridge.uno" SAL_DLLEXTENSION)), + rSMgr ); + + Reference < XBridgeFactory > rFactory( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory")), + OUString( RTL_CONSTASCII_USTRINGPARAM("bridgefac.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + if( rFactory.is() ) + { + + Reference < XBridge > rBridge = rFactory->createBridge( + OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")), + sProtocol, + rConnection, + new OInstanceProvider ); + { + // test the factory + Reference < XBridge > rBridge2 = rFactory->getBridge( OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")) ); + OSL_ASSERT( rBridge2.is() ); + OSL_ASSERT( rBridge2->getDescription() == rBridge->getDescription( ) ); + OSL_ASSERT( rBridge2->getName() == rBridge->getName() ); + OSL_ASSERT( rBridge2 == rBridge ); + } + + + Reference < XInterface > rInitialObject = rBridge->getInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("bridges-testobject")) ); + + if( rInitialObject.is() ) + { + printf( "got the remote object\n" ); + if( ! bReverse ) + { + // Reference < XComponent > rPerfTest( rInitialObject , UNO_QUERY ); +// if( rPerfTest.is() ) +// { +// // doPerformanceTest( rPerfTest ); +// } +// else +// { + testRemote( rInitialObject ); +// } + } + } +// Reference < XComponent > rComp( rBridge , UNO_QUERY ); +// rComp->dispose(); + + rInitialObject = Reference < XInterface > (); + printf( "Waiting...\n" ); + TimeValue value={bReverse ?1000 :2,0}; + osl_waitThread( &value ); + printf( "Closing...\n" ); + } + + Reference < XBridge > rBridge = rFactory->getBridge( OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")) ); +// OSL_ASSERT( ! rBridge.is() ); + } + + } + catch( DisposedException & e ) + { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "A remote object reference became invalid\n%s\n" , o.pData->buffer ); + } + catch( Exception &e ) + { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "Login failed, got an Exception !\n%s\n" , o.pData->buffer ); + } + + + Reference < XComponent > rComp( rSMgr , UNO_QUERY ); + rComp->dispose(); + } + printf( "Closed\n" ); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/testclient.java b/bridges/test/testclient.java new file mode 100644 index 000000000000..f2963f685b9f --- /dev/null +++ b/bridges/test/testclient.java @@ -0,0 +1,156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.IBridge; +import com.sun.star.connection.XConnector; +import com.sun.star.connection.XConnection; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.bridge.XInstanceProvider; + +import test.XCallMe; +import test.XTestFactory; + + +class MyInstanceProvider implements XInstanceProvider +{ + public Object getInstance( String sName ) + { + System.out.println( "getInstance called" ); + return new MyTestFactory(); + } + +} + + +class MyTestFactory implements XTestFactory +{ + public XCallMe createCallMe( ) throws com.sun.star.uno.RuntimeException + { + return new MyCallMe(); + } + + public test.XInterfaceTest createInterfaceTest( ) throws com.sun.star.uno.RuntimeException + { + return null; + } + +} +class MyCallMe implements XCallMe +{ + public String getsAttribute() throws com.sun.star.uno.RuntimeException + { + return ""; + } + public void setsAttribute( String _sattribute ) throws com.sun.star.uno.RuntimeException + { + } + + // Methods + public void call( /*IN*/String s, /*IN*/int nToDo ) throws test.TestBridgeException, com.sun.star.uno.RuntimeException + { + + } + public void callOneway( /*IN*/String s, /*IN*/int nToDo ) throws com.sun.star.uno.RuntimeException + { + System.out.println( "entering callOneway" ); +// this.wait( 5 ); + try { + Thread.currentThread().sleep( 4000 ); + } + catch ( java.lang.Exception e ) + { + System.out.println( e ); + } + System.out.println( "leaving callOneway" ); + } + public void callAgain( /*IN*/XCallMe callAgain, /*IN*/int nToCall ) throws com.sun.star.uno.RuntimeException + { + + } + public test.TestTypes transport( /*IN*/test.TestTypes types ) throws com.sun.star.uno.RuntimeException + { + return new test.TestTypes(); + } + +} + +public class testclient +{ + static void main( String[] args ) + { + try { + + com.sun.star.comp.servicemanager.ServiceManager smgr = + new com.sun.star.comp.servicemanager.ServiceManager(); + smgr.addFactories( new String[] { "com.sun.star.comp.connections.Connector" }); + + Object x = smgr.createInstance("com.sun.star.connection.Connector"); + if( x == null ) + { + System.out.println( "couldn't create connector\n" ); + return; + } + + + XConnector xConnector = + UnoRuntime.queryInterface( XConnector.class , x ); + + XConnection xConnection = xConnector.connect(args[0]); + + if( null != xConnection ) + { + System.out.println( "after connect" ); + String rootOid = "OfficeDaemon.Factory"; + com.sun.star.uno.IBridge bridge = (IBridge ) UnoRuntime.getBridgeByName( + "java", + null, + "remote", + null, + new Object[]{"iiop", xConnection, new MyInstanceProvider()}); + + System.out.println( "after building bridge" ); +// Object rInitialObject = m_bridge.mapInterfaceFrom(rootOid, XInterface.class); +// XTestFactory rFactory = +// UnoRuntime.queryInterface(XTestFactory.class,rInitialObject ); + +// XCallMe callMerFactory-> + Thread.currentThread().sleep( 100000 ); + } + } + catch( com.sun.star.uno.Exception e) + { + System.out.println( "Exception thrown" ); + } + catch( java.lang.Exception e) + { + System.out.println( "java.lang.Exception thrown" ); + } + + System.out.println( "exiting" ); + } +} diff --git a/bridges/test/testcomp.cxx b/bridges/test/testcomp.cxx new file mode 100644 index 000000000000..864279827a6b --- /dev/null +++ b/bridges/test/testcomp.cxx @@ -0,0 +1,801 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <string.h> +#include <stdlib.h> +#include <osl/time.h> + +#include <uno/threadpool.h> + +#include <osl/mutex.hxx> +#include <osl/diagnose.h> + +#include <test/XTestFactory.hpp> +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/bridge/XInstanceProvider.hpp> + +#include <com/sun/star/registry/XImplementationRegistration.hpp> + +#include <com/sun/star/test/performance/XPerformanceTest.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/weak.hxx> + +using namespace ::test; +using namespace ::rtl; +using namespace ::test; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::test::performance; + +#include "testcomp.h" + + +void parseCommandLine( char *argv[] , + ::rtl::OUString *pConnection , ::rtl::OUString *pProtocol , + sal_Bool *pbLatency , sal_Bool *pbReverse) +{ + sal_Int32 nArgIndex = 1; + if( ! strcmp( argv[1] , "-r" ) ) + { + nArgIndex = 2; + *pbReverse = sal_True; + } + else if( ! strcmp( argv[1] , "-latency" ) ) + { + *pbLatency = sal_True; + nArgIndex = 2; + } + + OUString sTemp = OUString::createFromAscii( argv[nArgIndex] ); + sal_Int32 nIndex = sTemp.indexOf( ';' ); + if( -1 == nIndex ) + { + *pConnection = sTemp; + *pProtocol = OUString( RTL_CONSTASCII_USTRINGPARAM( "iiop" ) ); + } + else + { + *pConnection = sTemp.copy( 0 , nIndex ); + *pProtocol = sTemp.copy( nIndex+1, sTemp.getLength() - (nIndex+1) ); + } +} + +Any OInstanceProvider::queryInterface( const Type & aType ) throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( aType , + SAL_STATIC_CAST( XInstanceProvider * , this ) ); + if( a.hasValue() ) + { + return a; + } + return OWeakObject::queryInterface( aType ); +} + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + OInstanceProvider::getInstance( const ::rtl::OUString& sObjectName ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException) +{ + // Tries to get the PerformanceTestObject + if( sObjectName == OUString( RTL_CONSTASCII_USTRINGPARAM( "TestRemoteObject" ) ) ) + { + return m_rSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.test.performance.PerformanceTestObject") ) ); + } + return Reference < XInterface > ( (::cppu::OWeakObject * ) new OTestFactory() ); +} + +class ServiceImpl + : public XServiceInfo + , public XPerformanceTest +{ + OUString _aDummyString; + Any _aDummyAny; + Sequence< Reference< XInterface > > _aDummySequence; + ComplexTypes _aDummyStruct; + RuntimeException _aDummyRE; + + sal_Int32 _nRef; + +public: + ServiceImpl() + : _nRef( 0 ) + {} + ServiceImpl( const Reference< XMultiServiceFactory > & /* xMgr */) + : _nRef( 0 ) + {} + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& aType ) throw(::com::sun::star::uno::RuntimeException) + { + // execution time remains appr. constant any time + Any aRet; + if (aType == ::getCppuType( (const Reference< XInterface > *)0 )) + { + void * p = (XInterface *)(XPerformanceTest *)this; + aRet.setValue( &p, ::getCppuType( (const Reference< XInterface > *)0 ) ); + } + if (aType == ::getCppuType( (const Reference< XPerformanceTest > *)0 )) + { + void * p = (XPerformanceTest *)this; + aRet.setValue( &p, ::getCppuType( (const Reference< XPerformanceTest > *)0 ) ); + } + if (! aRet.hasValue()) + { + void * p = (XPerformanceTest *)this; + Any aDummy( &p, ::getCppuType( (const Reference< XPerformanceTest > *)0 ) ); + } + return aRet; + } + virtual void SAL_CALL acquire() throw() + { osl_incrementInterlockedCount( &_nRef ); } + virtual void SAL_CALL release() throw() + { if (! osl_decrementInterlockedCount( &_nRef )) delete this; } + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException); + + // Attributes + virtual sal_Int32 SAL_CALL getLong_attr() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setLong_attr( sal_Int32 /* _attributelong */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual sal_Int64 SAL_CALL getHyper_attr() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setHyper_attr( sal_Int64 /* _attributehyper */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual float SAL_CALL getFloat_attr() throw(::com::sun::star::uno::RuntimeException) + { return 0.0; } + virtual void SAL_CALL setFloat_attr( float /* _attributefloat */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual double SAL_CALL getDouble_attr() throw(::com::sun::star::uno::RuntimeException) + { return 0.0; } + virtual void SAL_CALL setDouble_attr( double /* _attributedouble */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual OUString SAL_CALL getString_attr() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyString; } + virtual void SAL_CALL setString_attr( const ::rtl::OUString& /* _attributestring */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Reference< XInterface > SAL_CALL getInterface_attr() throw(::com::sun::star::uno::RuntimeException) + { return Reference< XInterface >(); } + virtual void SAL_CALL setInterface_attr( const Reference< XInterface >& /* _attributeinterface */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Any SAL_CALL getAny_attr() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyAny; } + virtual void SAL_CALL setAny_attr( const Any& /* _attributeany */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Sequence< Reference< XInterface > > SAL_CALL getSequence_attr() throw(::com::sun::star::uno::RuntimeException) + { return _aDummySequence; } + virtual void SAL_CALL setSequence_attr( const Sequence< Reference< XInterface > >& /* _attributesequence */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual ComplexTypes SAL_CALL getStruct_attr() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyStruct; } + virtual void SAL_CALL setStruct_attr( const ::com::sun::star::test::performance::ComplexTypes& /* _attributestruct */) throw(::com::sun::star::uno::RuntimeException) + {} + + // Methods + virtual sal_Int32 SAL_CALL getLong() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setLong( sal_Int32 /* _long */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual sal_Int64 SAL_CALL getHyper() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setHyper( sal_Int64 /* _hyper */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual float SAL_CALL getFloat() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setFloat( float /* _float */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual double SAL_CALL getDouble() throw(::com::sun::star::uno::RuntimeException) + { return 0; } + virtual void SAL_CALL setDouble( double /* _double */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual OUString SAL_CALL getString() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyString; } + virtual void SAL_CALL setString( const ::rtl::OUString& /* _string */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Reference< XInterface > SAL_CALL getInterface() throw(::com::sun::star::uno::RuntimeException) + { return Reference< XInterface >(); } + virtual void SAL_CALL setInterface( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& /* _interface */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Any SAL_CALL getAny() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyAny; } + virtual void SAL_CALL setAny( const ::com::sun::star::uno::Any& /* _any */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Sequence< Reference< XInterface > > SAL_CALL getSequence() throw(::com::sun::star::uno::RuntimeException) + { return _aDummySequence; } + virtual void SAL_CALL setSequence( const Sequence< Reference< XInterface > >& /*_sequence */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual ComplexTypes SAL_CALL getStruct() throw(::com::sun::star::uno::RuntimeException) + { return _aDummyStruct; } + virtual void SAL_CALL setStruct( const ::com::sun::star::test::performance::ComplexTypes& /* c */) throw(::com::sun::star::uno::RuntimeException) + {} + + virtual void SAL_CALL async() throw(::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL sync() throw(::com::sun::star::uno::RuntimeException) + {} + virtual ComplexTypes SAL_CALL complex_in( const ::com::sun::star::test::performance::ComplexTypes& aVal ) throw(::com::sun::star::uno::RuntimeException) + { return aVal; } + virtual ComplexTypes SAL_CALL complex_inout( ::com::sun::star::test::performance::ComplexTypes& aVal ) throw(::com::sun::star::uno::RuntimeException) + { return aVal; } + virtual void SAL_CALL complex_oneway( const ::com::sun::star::test::performance::ComplexTypes& /* aVal */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual void SAL_CALL complex_noreturn( const ::com::sun::star::test::performance::ComplexTypes& /* aVal */) throw(::com::sun::star::uno::RuntimeException) + {} + virtual Reference< XPerformanceTest > SAL_CALL createObject() throw(::com::sun::star::uno::RuntimeException) + { return new ServiceImpl(); } + virtual void SAL_CALL raiseRuntimeException( ) throw(::com::sun::star::uno::RuntimeException) + { throw _aDummyRE; } +}; + + +void ServiceImpl::async() throw(::com::sun::star::uno::RuntimeException) +{} + +// XServiceInfo +//__________________________________________________________________________________________________ +OUString ServiceImpl::getImplementationName() + throw (RuntimeException) +{ + return OUString( ); +} +//__________________________________________________________________________________________________ +sal_Bool ServiceImpl::supportsService( const OUString & /* rServiceName */) + throw (RuntimeException) +{ + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > ServiceImpl::getSupportedServiceNames() + throw (RuntimeException) +{ + return Sequence< OUString > (); +} + +/****************** + * OCallMe + * + *****************/ + +Any OCallMe::queryInterface( const Type & aType ) throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( aType, + SAL_STATIC_CAST( XCallMe * , this ) ); + + if( a.hasValue() ) + { + return a; + } + + return OWeakObject::queryInterface( aType ); +} + +void OCallMe::call( const ::rtl::OUString& s, sal_Int32 nToDo ) + throw( RuntimeException, ::test::TestBridgeException) +{ + if( nToDo < 0 ) + { + throw TestBridgeException(); + } + + OUString sDummy; + if( ! nToDo ) { + OString o = OUStringToOString( s,RTL_TEXTENCODING_ASCII_US); + printf( "%s\n" , o.pData->buffer ); + } + for( sal_Int32 i = 0 ; i < nToDo ; i ++ ) + { + sDummy += s; + } +} + +void SAL_CALL OCallMe::drawLine( sal_Int32 /* x1 */, sal_Int32 /* y1 */, sal_Int32 /* x2 */, sal_Int32 /* y2 */) + throw(::com::sun::star::uno::RuntimeException) +{ + // do nothings +} + +void OCallMe::callOneway( const ::rtl::OUString& /* s */, sal_Int32 nToDo ) + throw(RuntimeException) +{ + OUString sDummy; + m_nLastToDos = nToDo; + + + if( nToDo ) + { + printf( "+" ); + fflush( stdout ); + + TimeValue val = { nToDo , 0 }; + osl_waitThread( &val ); + printf( "-\n" ); + } + +} + +::test::TestTypes SAL_CALL OCallMe::transport( const ::test::TestTypes& types ) + throw(::com::sun::star::uno::RuntimeException) +{ + return types; +} + +::rtl::OUString OCallMe::getsAttribute() throw(RuntimeException) +{ + return m_sAttribute; +} +void OCallMe::setsAttribute( const ::rtl::OUString& _sattribute ) + throw(RuntimeException) +{ + m_sAttribute = _sattribute; +} +void OCallMe::callAgain( const Reference< ::test::XCallMe >& callAgainArg, + sal_Int32 nToCall ) throw(RuntimeException) +{ + ::osl::MutexGuard guard( m_mutex ); + if( nToCall %2 ) + { + printf( "Deadlocktest pong %" SAL_PRIdINT32 "\n", nToCall ); + } + else + { + printf( "Deadlocktest ping %" SAL_PRIdINT32 "\n", nToCall ); + } + if( nToCall ) + { + callAgainArg->callAgain( Reference< XCallMe > ( (XCallMe *) this ) , nToCall -1 ); + } +} + +/******************** + * OInterfaceTest + * + *******************/ +Any OInterfaceTest::queryInterface( const Type & aType ) throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( aType, + SAL_STATIC_CAST( XInterfaceTest * , this ) ); + if( a.hasValue() ) + { + return a; + } + return OWeakObject::queryInterface( aType ); +} + + +void OInterfaceTest::setIn( + const Reference< ::test::XCallMe >& callback ) + throw(RuntimeException) +{ + m_rCallMe = callback; + call(); +} + +void OInterfaceTest::setInOut( Reference< ::test::XCallMe >& callback ) + throw(RuntimeException) +{ + Reference< XCallMe > r = m_rCallMe; + m_rCallMe = callback; + callback = r; + call(); +} + + +void OInterfaceTest::getOut( Reference< ::test::XCallMe >& callback ) + throw(RuntimeException) +{ + callback = m_rCallMe; +} + +Reference< ::test::XCallMe > OInterfaceTest::get( ) + throw(RuntimeException) +{ + call(); + return m_rCallMe; +} + +void OInterfaceTest::call() +{ + if( m_rCallMe.is() ) + { + m_rCallMe->call( OUString( RTL_CONSTASCII_USTRINGPARAM("This is my String during a callback!")) , 5); + } +} + + +Any OTestFactory::queryInterface( const Type & aType ) throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( aType, + SAL_STATIC_CAST( XTestFactory * , this ) ); + + if( a.hasValue() ) + { + return a; + } + + return OWeakObject::queryInterface( aType ); +} + +Reference< ::test::XCallMe > OTestFactory::createCallMe( ) + throw(RuntimeException) +{ + return Reference< XCallMe > ( (XCallMe * ) new OCallMe() ); +} + +Reference< ::test::XInterfaceTest > SAL_CALL OTestFactory::createInterfaceTest( ) + throw(RuntimeException) +{ + return Reference < XInterfaceTest > ( (XInterfaceTest * ) new OInterfaceTest() ); +} + + + + +// class OInstanceProvider : +// public ::cppu::OWeakObject, +// public XInstanceProvider +// { +// public: +// OInstanceProvider( ){} +// ~OInstanceProvider(){ printf( "instance provider dies\n" );} +// public: +// // XInterface +// Any SAL_CALL queryInterface( const Type & aType); +// void SAL_CALL acquire() { OWeakObject::acquire(); } +// void SAL_CALL release() { OWeakObject::release(); } + +// public: +// virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL +// getInstance( const ::rtl::OUString& sObjectName ) +// throw( ::com::sun::star::container::NoSuchElementException, +// ::com::sun::star::uno::RuntimeException); +// }; + + + + + + + + +double getCallsPerSec( const Reference < XCallMe > &rCall , int nLoops, int nToDo ) +{ + TimeValue aStartTime, aEndTime; + osl_getSystemTime( &aStartTime ); + for( sal_Int32 i = 0; i < nLoops; i ++ ) + { + rCall->call( OUString( RTL_CONSTASCII_USTRINGPARAM("Performance test string")) , nToDo ); + } + osl_getSystemTime( &aEndTime ); + + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + return fEnd-fStart; +} + +double getCallsPerSecOneway( const Reference < XCallMe > &rCall , + int nLoops, + int nToDo, + double *pdAfterExecution + ) +{ + TimeValue aStartTime, aEndTime, aAfterExecution; + osl_getSystemTime( &aStartTime ); + for( sal_Int32 i = 0; i < nLoops; i ++ ) + { +// rCall->callOneway( OUString( RTL_CONSTASCII_USTRINGPARAM("Performance test string" )), 0 ); + rCall->drawLine( 0 , 0 , 500 , 123 ); + } + osl_getSystemTime( &aEndTime ); + + rCall->call( OUString( RTL_CONSTASCII_USTRINGPARAM("Performance test string")) , nToDo ); + osl_getSystemTime( &aAfterExecution ); + + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + *pdAfterExecution = (double)aAfterExecution.Seconds + + ((double)aAfterExecution.Nanosec / 1000000000.0) - fStart; + return fEnd-fStart; +} + +void testOnewayPerformanceOnTwoInterfaces( + const Reference < XCallMe > &rRemote1, const Reference < XCallMe > &rRemote2 ) +{ + printf( "Doing oneway performance test on two interfaces ...\n" ); + const sal_Int32 nLoops = 10000; + TimeValue aStartTime, aEndTime; + osl_getSystemTime( &aStartTime ); + for( sal_Int32 i = 0; i < nLoops ; i ++ ) + { + rRemote1->drawLine( 0 , 0 , 500 , 123 ); + rRemote2->drawLine( 0 , 0 , 500 , 123 ); + } + osl_getSystemTime( &aEndTime ); + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + + printf( "Overhead per Call [ms] %g\n" , ((fEnd-fStart)/((double)nLoops/1000 ))/2. ); +} + +void testPerformance( const Reference < XCallMe > &rRemote, + const Reference < XCallMe > &rLocal ) +{ + OUString aTestString; + + sal_Int32 nDoSomething = 1; + sal_Int32 nCalls = 80000; + double dRemote, dLocal,dAfterExecution; + + printf( "performance test oneway...\n" ); + dLocal = getCallsPerSecOneway( rLocal , nCalls , nDoSomething , &dAfterExecution); + dRemote = getCallsPerSecOneway( rRemote , nCalls , nDoSomething , &dAfterExecution); + printf( "Local=%g s," + "Remote : %g s\n" , dLocal, dRemote ); + if( dLocal > 0. ) + { + printf( "Remote/Local : %g\n", dRemote/dLocal ); + } + + printf( "Overhead per Call [ms] %g\n" , (dRemote - dLocal)/((double)nCalls/1000 ) ); + printf( "Overhead per Call after completion [ms] %g\n" , (dAfterExecution - dLocal)/((double)nCalls/1000 ) ); + + nCalls = 2000; + + printf( "Doing performance test ...\n" ); + dRemote = getCallsPerSec( rRemote , nCalls , nDoSomething ); + dLocal = getCallsPerSec( rLocal , nCalls , nDoSomething ); + printf( "Local=%g s,\n" + "Remote=%g s\n" , dLocal, dRemote ); + if( dLocal > 0. ) + { + printf( "Remote/Local : %g\n", dRemote/dLocal ); + } + printf( "Overhead per synchron Call [ms] %g\n" , ((dRemote - dLocal)/((double)nCalls/1000 )) ); +} + +void testException( const Reference < XCallMe > &r ) +{ + try { + r->call( OUString( RTL_CONSTASCII_USTRINGPARAM("dummy")) , -1 ); + OSL_ASSERT( ! "no exception flown !" ); + } + catch( TestBridgeException & e ) + { + // Exception flew successfully ! + } + catch( Exception & e ) + { + OSL_ASSERT( ! "only base class of exception could be catched!" ); + } + catch(...) + { + OSL_ASSERT(! "wrong unknown exception !" ); + } +} + +void testSequenceOfCalls( const Reference< XCallMe > & rRCallMe ) +{ + printf( "Testing sequence of calls\n" ); + for( sal_Int32 i = 0 ; i < 800 ; i ++ ) + { + rRCallMe->callOneway( OUString( RTL_CONSTASCII_USTRINGPARAM("hifuj" )), 0 ); + } +} + +void testAllTypes( const Reference < XCallMe > & rRCallMe ) +{ + printf( "Testing all types\n" ); + + for( sal_Int32 i = 0; i < 32 ; i ++ ) + { + + TestTypes types; + types.Bool = sal_True; + types.Char = L'i'; + types.Byte = -12; + types.Short = -32000; + types.UShort = (sal_uInt16 ) (1 << i); + types.Long = -123; + types.ULong = 1 << i; + types.Hyper = 50; + types.UHyper = 1 << i*2; + types.Float = (float)123.239; + types.Double = 1279.12490012; + types.String = OUString( RTL_CONSTASCII_USTRINGPARAM("abcdefghijklmnopqrstuvwxyz")); + types.Interface = Reference< XInterface >( rRCallMe , UNO_QUERY); + types.Any <<= types.Double; + + TestTypes retTypes = rRCallMe->transport( types ); + + OSL_ASSERT( ( types.Bool && retTypes.Bool ) || ( ! types.Bool && ! retTypes.Bool ) ); + OSL_ASSERT( types.Char == retTypes.Char ); + OSL_ASSERT( types.Byte == retTypes.Byte ); + OSL_ASSERT( types.Short == retTypes.Short ); + OSL_ASSERT( types.UShort == retTypes.UShort ); + OSL_ASSERT( types.Long == retTypes.Long ); + OSL_ASSERT( types.ULong == retTypes.ULong ); + OSL_ASSERT( types.Hyper == retTypes.Hyper ); + OSL_ASSERT( types.UHyper == retTypes.UHyper ); + OSL_ASSERT( types.Float == retTypes.Float ); + OSL_ASSERT( types.Double == retTypes.Double ); + OSL_ASSERT( types.String == retTypes.String ); + OSL_ASSERT( types.Interface == retTypes.Interface ); + OSL_ASSERT( types.Any == retTypes.Any ); + } + +} + +void testRemote( const Reference< XInterface > &rRemote ) +{ + char a; + getCppuType( (sal_Int8*)&a ); + + Reference< XTestFactory > rRFact( rRemote , UNO_QUERY ); + if( ! rRFact.is() ) + { + printf( "remote object doesn't support XTestFactory\n" ); + return; + } + OSL_ASSERT( rRFact.is() ); + Reference< XCallMe > rLCallMe = (XCallMe * ) new OCallMe(); + Reference< XCallMe > rRCallMe = rRFact->createCallMe(); + + testAllTypes( rLCallMe ); + testAllTypes( rRCallMe ); + + printf( "Testing exception local ...\n" ); + testException( rLCallMe ); + printf( "Testing exception remote ...\n" ); + testException( rRCallMe ); + + //-------------------- + // Test attributes + //---------------------- + OUString ow( RTL_CONSTASCII_USTRINGPARAM( "dum didel dum dideldei" )); + rLCallMe->setsAttribute( ow ); + OSL_ASSERT( rLCallMe->getsAttribute() == ow ); + + rRCallMe->setsAttribute( ow ); + OSL_ASSERT( rRCallMe->getsAttribute() == ow ); + + //------------------- + // Performance test + //------------------- + testPerformance( rRCallMe , rLCallMe ); + testOnewayPerformanceOnTwoInterfaces( rRFact->createCallMe(), rRCallMe ); + + //---------------- + // Test sequence + //---------------- + testSequenceOfCalls( rRCallMe ); + + + // test triple to check if transporting the same interface multiple + // times causes any problems + Reference< XInterfaceTest > rRTest = rRFact->createInterfaceTest(); + Reference< XInterfaceTest > rRTest2 = rRFact->createInterfaceTest(); + Reference< XInterfaceTest > rRTest3 = rRFact->createInterfaceTest(); + + rRTest->setIn( rRCallMe ); + rRTest2->setIn( rRCallMe ); + rRTest3->setIn( rRCallMe ); + + OSL_ASSERT( rRTest->get() == rRCallMe ); + OSL_ASSERT( rRTest2->get() == rRCallMe ); + OSL_ASSERT( rRTest3->get() == rRCallMe ); + + rRTest->setIn( rLCallMe ); + rRTest2->setIn( rLCallMe ); + rRTest3->setIn( rLCallMe ); + + { + Reference< XCallMe > rLCallMe1 = (XCallMe * ) new OCallMe(); + Reference< XCallMe > rLCallMe2 = (XCallMe * ) new OCallMe(); + Reference< XCallMe > rLCallMe3 = (XCallMe * ) new OCallMe(); + rRTest->setIn( rLCallMe1 ); + rRTest2->setIn( rLCallMe2 ); + rRTest3->setIn( rLCallMe3 ); + OSL_ASSERT( rRTest->get() == rLCallMe1 ); + OSL_ASSERT( rRTest2->get() == rLCallMe2 ); + OSL_ASSERT( rRTest3->get() == rLCallMe3 ); + + rRTest->setIn( rLCallMe ); + rRTest2->setIn( rLCallMe ); + rRTest3->setIn( rLCallMe ); + + OSL_ASSERT( rRTest->get() == rLCallMe ); + OSL_ASSERT( rRTest2->get() == rLCallMe ); + OSL_ASSERT( rRTest3->get() == rLCallMe ); + } + + Reference < XCallMe > r = rRCallMe; + rRTest->setInOut( r ); + OSL_ASSERT( r == rLCallMe ); + OSL_ASSERT( ! ( r == rRCallMe ) ); + + // test empty references + rRTest->setIn( Reference < XCallMe > () ); + + //-------------------------------- + // test thread deadlocking + //-------------------------------- + rLCallMe->callAgain( rRCallMe, 20 ); + +} + + + + + + +Reference <XInterface > createComponent( const ::rtl::OUString &sService , + const ::rtl::OUString &sDllName, + const Reference < XMultiServiceFactory > &rSMgr ) +{ + Reference< XInterface > rInterface; + rInterface = rSMgr->createInstance( sService ); + + if( ! rInterface.is() ) + { + // erst registrieren + Reference < XImplementationRegistration > rReg ( + rSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.registry.ImplementationRegistration" ))), + UNO_QUERY ); + + OSL_ASSERT( rReg.is() ); + OUString aDllName = sDllName; + + try + { + rReg->registerImplementation( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.SharedLibrary" )), + aDllName, + Reference< XSimpleRegistry > () ); + rInterface = rSMgr->createInstance( sService ); + } + catch( Exception & ) + { + printf( "couldn't register dll %s\n" , + OUStringToOString( aDllName, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + } + return rInterface; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/testcomp.h b/bridges/test/testcomp.h new file mode 100644 index 000000000000..ad96c7262433 --- /dev/null +++ b/bridges/test/testcomp.h @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stdio.h> + +#include <com/sun/star/bridge/XInstanceProvider.hpp> +#include <osl/thread.hxx> + + +void parseCommandLine( char *argv[] , + ::rtl::OUString *pProtocol , ::rtl::OUString *pConnection , + sal_Bool *pbLatency , sal_Bool *pbReverse); + + +Reference< XInterface > createComponent( + const ::rtl::OUString &sServiceName, + const ::rtl::OUString &sDllName, + const Reference < XMultiServiceFactory > & rSMgr ); + +class OInterfaceTest : + public ::cppu::OWeakObject, + public XInterfaceTest +{ +public: + OInterfaceTest() {} + ~OInterfaceTest() {} + +public: + // XInterface + Any SAL_CALL queryInterface( const com::sun::star::uno::Type & aType) throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + void SAL_CALL release() throw() { OWeakObject::release(); } + +public: + virtual void SAL_CALL setIn( const ::com::sun::star::uno::Reference< ::test::XCallMe >& callback ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInOut( ::com::sun::star::uno::Reference< ::test::XCallMe >& callback ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL getOut( ::com::sun::star::uno::Reference< ::test::XCallMe >& callback ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::test::XCallMe > SAL_CALL get( ) throw(::com::sun::star::uno::RuntimeException); +private: + void call(); + +private: + Reference < XCallMe > m_rCallMe; +}; + + +class OCallMe : + public ::cppu::OWeakObject, + public XCallMe +{ +public: + OCallMe() : m_nLastToDos(-1) {} + ~OCallMe() {} + +public: + // XInterface + Any SAL_CALL queryInterface( const com::sun::star::uno::Type & aType) throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL acquire()throw() { OWeakObject::acquire(); } + void SAL_CALL release()throw() { OWeakObject::release(); } +public: + // XCallMe + virtual void SAL_CALL call( const ::rtl::OUString& s, sal_Int32 nToDo ) + throw(::com::sun::star::uno::RuntimeException, + ::test::TestBridgeException); + virtual void SAL_CALL callOneway( const ::rtl::OUString& s, sal_Int32 nToDo ) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL drawLine( sal_Int32 x1, sal_Int32 y1 , sal_Int32 x2 , sal_Int32 y2 ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getsAttribute() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setsAttribute( const ::rtl::OUString& _sattribute ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL callAgain( const ::com::sun::star::uno::Reference< ::test::XCallMe >& callAgain, + sal_Int32 nToCall ) throw(::com::sun::star::uno::RuntimeException); + + virtual ::test::TestTypes SAL_CALL transport( const ::test::TestTypes& types ) + throw(::com::sun::star::uno::RuntimeException); + + ::osl::Mutex m_mutex; + ::rtl::OUString m_sAttribute; + sal_Int32 m_nLastToDos; +}; + +class OTestFactory : + public ::cppu::OWeakObject, + public XTestFactory +{ +public: + OTestFactory() {} + ~OTestFactory() {} + +public: + // XInterface + Any SAL_CALL queryInterface( const com::sun::star::uno::Type & aType ) throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + void SAL_CALL release() throw() { OWeakObject::release(); } +public: + virtual ::com::sun::star::uno::Reference< ::test::XCallMe > SAL_CALL createCallMe( ) + throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::test::XInterfaceTest > SAL_CALL createInterfaceTest( ) + throw(::com::sun::star::uno::RuntimeException); + +}; + + +class OInstanceProvider : + public ::cppu::OWeakObject, + public XInstanceProvider +{ +public: + OInstanceProvider( ){} + OInstanceProvider( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & r ) : + m_rSMgr( r ) + {} + ~OInstanceProvider(){ printf( "instance provider dies\n" );} +public: + // XInterface + Any SAL_CALL queryInterface( const Type & aType)throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL acquire()throw() { OWeakObject::acquire(); } + void SAL_CALL release() throw() { OWeakObject::release(); } + +public: + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + getInstance( const ::rtl::OUString& sObjectName ) + throw( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_rSMgr; +}; + +void testRemote( const Reference< XInterface > &rRemote ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/testoffice.cxx b/bridges/test/testoffice.cxx new file mode 100644 index 000000000000..9e90702e036c --- /dev/null +++ b/bridges/test/testoffice.cxx @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <osl/time.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> + +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/connection/XConnector.hpp> + +#include <com/sun/star/bridge/XBridgeFactory.hpp> + +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> + +#include <com/sun/star/text/XTextDocument.hpp> + +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <com/sun/star/lang/XComponent.hpp> + +#include <com/sun/star/frame/XComponentLoader.hpp> + +#include <cppuhelper/weak.hxx> + +#include <test/XTestFactory.hpp> + +using namespace ::test; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::connection; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::text; + +#include "testcomp.h" + +#ifdef SAL_W32 +#include <conio.h> +#endif + + +void mygetchar() +{ +#ifdef SAL_W32 + _getch(); +#else + getchar(); +#endif +} + + +void testPipe( const Reference < XMultiServiceFactory > & rSmgr ) +{ + Reference < XOutputStream > rOut( + rSmgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pipe" )) ), + UNO_QUERY ); + + OSL_ASSERT( rOut.is() ); + + { + Sequence < sal_Int8 > seq( 10 ); + seq.getArray()[0] = 42; + rOut->writeBytes( seq ); + } + + + { + Sequence < sal_Int8 > seq; + Reference < XInputStream > rIn( rOut , UNO_QUERY ); + if( ! ( rIn->available() == 10) ) + printf( "wrong bytes available\n" ); + if( ! ( rIn->readBytes( seq , 10 ) == 10 ) ) + printf( "wrong bytes read\n" ); + if( ! ( 42 == seq.getArray()[0] ) ) + printf( "wrong element in sequence\n" ); + +// OSL_ASSERT( 0 ); + } +} +#include<stdio.h> +#include<string.h> + +void testWriter( const Reference < XComponent > & rCmp ) +{ + + Reference< XTextDocument > rTextDoc( rCmp , UNO_QUERY ); + + Reference< XText > rText = rTextDoc->getText(); + Reference< XTextCursor > rCursor = rText->createTextCursor(); + Reference< XTextRange > rRange ( rCursor , UNO_QUERY ); + + char pcText[1024]; + pcText[0] = 0; + printf( "pleast type any text\n" ); + while( sal_True ) + { + scanf( "%s" , pcText ); + + if( !strcmp( pcText , "end" ) ) + { + break; + } + + if ( strlen( pcText ) < sizeof(pcText)-1 ) + strcat( pcText , " " ); // #100211# - checked + + rText->insertString( rRange , OUString::createFromAscii( pcText ) , sal_False ); + } +} + +void testDocument( const Reference < XMultiServiceFactory > & rSmgr ) +{ + Reference < XComponentLoader > rLoader( + rSmgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop" ))), + UNO_QUERY ); + + OSL_ASSERT( rLoader.is() ); + + sal_Char *urls[] = { + "private:factory/swriter", + "private:factory/scalc", + "private:factory/sdraw", + "http://www.heise.de", + "file://h|/remote_interfaces.sdw" + }; + + sal_Char *docu[]= { + "a new writer document ...\n", + "a new calc document ...\n", + "a new draw document ...\n", + "www.heise.de\n", + "the remote_interfaces.sdw doc\n" + }; + + sal_Int32 i; + for( i = 0 ; i < 1 ; i ++ ) + { + printf( "press any key to open %s\n" , docu[i] ); + mygetchar(); + + Reference< XComponent > rComponent = + rLoader->loadComponentFromURL( + OUString::createFromAscii( urls[i] ) , + OUString( RTL_CONSTASCII_USTRINGPARAM("_blank")), + 0 , + Sequence < ::com::sun::star::beans::PropertyValue >() ); + + testWriter( rComponent ); + printf( "press any key to close the document\n" ); + mygetchar(); + rComponent->dispose(); + } + +} + +void doSomething( const Reference < XInterface > &r ) +{ + Reference < XNamingService > rName( r, UNO_QUERY ); + if( rName.is() ) + { + printf( "got the remote naming service !\n" ); + Reference < XInterface > rXsmgr = rName->getRegisteredObject( + OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice.ServiceManager" )) ); + + Reference < XMultiServiceFactory > rSmgr( rXsmgr , UNO_QUERY ); + if( rSmgr.is() ) + { + printf( "got the remote service manager !\n" ); + testPipe( rSmgr ); + testDocument( rSmgr ); + } + } +} + + +int main( int argc, char *argv[] ) +{ + if( argc < 2 ) + { + printf( "usage : testclient host:port" ); + return 0; + } + + OUString sConnectionString; + OUString sProtocol; + sal_Bool bLatency = sal_False; + sal_Bool bReverse = sal_False; + parseCommandLine( argv , &sConnectionString , &sProtocol , &bLatency , &bReverse ); + { + Reference< XMultiServiceFactory > rSMgr = createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM( "client.rdb" ) ) ); + + // just ensure that it is registered + + Reference < XConnector > rConnector( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Connector")), + OUString( RTL_CONSTASCII_USTRINGPARAM("connector.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.Bridge.iiop")), + OUString( RTL_CONSTASCII_USTRINGPARAM("remotebridge.uno" SAL_DLLEXTENSION)), + rSMgr ); + + Reference < XBridgeFactory > rFactory( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory")), + OUString( RTL_CONSTASCII_USTRINGPARAM("bridgefac.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + try + { + if( rFactory.is() && rConnector.is() ) + { + Reference < XConnection > rConnection = + rConnector->connect( sConnectionString ); + + Reference < XBridge > rBridge = rFactory->createBridge( + OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")), + sProtocol, + rConnection, + Reference < XInstanceProvider > () ); + + Reference < XInterface > rInitialObject + = rBridge->getInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("NamingService")) ); + + if( rInitialObject.is() ) + { + printf( "got the remote object\n" ); + doSomething( rInitialObject ); + } + TimeValue value={2,0}; + osl_waitThread( &value ); + } + } + catch (... ) { + printf( "Exception thrown\n" ); + } + + Reference < XComponent > rComp( rSMgr , UNO_QUERY ); + rComp->dispose(); + } + //_getch(); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/testsameprocess.cxx b/bridges/test/testsameprocess.cxx new file mode 100644 index 000000000000..35003986e386 --- /dev/null +++ b/bridges/test/testsameprocess.cxx @@ -0,0 +1,218 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <osl/time.h> + +#include <osl/mutex.hxx> +#include <osl/thread.hxx> + +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/bridge/XBridgeFactory.hpp> +#include <com/sun/star/connection/XAcceptor.hpp> +#include <com/sun/star/connection/XConnector.hpp> + +#include <com/sun/star/lang/XComponent.hpp> + +#include <cppuhelper/weak.hxx> + +#include <test/XTestFactory.hpp> + + +using namespace ::test; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::connection; + +#ifdef SAL_W32 +#include <conio.h> +#endif + +#include "testcomp.h" +#include "osl/mutex.h" + +/********* + * + ********/ + +class MyThread : + public Thread +{ +public: + MyThread( const Reference< XAcceptor > &r , + const Reference< XBridgeFactory > &rFactory, + const OUString &sConnectionDescription) : + m_rAcceptor( r ), + m_rBridgeFactory ( rFactory ), + m_sConnectionDescription( sConnectionDescription ) + {} + virtual void SAL_CALL run(); + +private: + Reference < XAcceptor > m_rAcceptor; + Reference < XBridgeFactory > m_rBridgeFactory; + OUString m_sConnectionDescription; +}; + + + +void MyThread::run() +{ + + while ( sal_True ) + { + try + { + Reference < XConnection > rConnection = + m_rAcceptor->accept( m_sConnectionDescription ); + + if( ! rConnection.is() ) + { + break; + } + + Reference < XBridge > rBridge = + m_rBridgeFactory->createBridge( + OUString() , + OUString( RTL_CONSTASCII_USTRINGPARAM("iiop")) , + rConnection , + (XInstanceProvider * ) new OInstanceProvider ); + + + } + catch ( ... ) + { + printf( "Exception was thrown by acceptor thread\n" ); + break; + } + } +} + + +int main( int argc, char *argv[] ) +{ + if( argc < 2 ) + { + printf( "usage : testsamprocess host:port\n" ); + return 0; + } + + { + Reference< XMultiServiceFactory > rSMgr = createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM( "client.rdb" ) ) ); + + Reference < XConnector > rConnector( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Connector")), + OUString( RTL_CONSTASCII_USTRINGPARAM("connector.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + Reference < XAcceptor > rAcceptor( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Acceptor")), + OUString( RTL_CONSTASCII_USTRINGPARAM("acceptor.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + // just ensure that it is registered +// createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.Bridge.iiop")), +// OUString( RTL_CONSTASCII_USTRINGPARAM("iiopbrdg" SAL_DLLEXTENSION)), +// rSMgr ); + + Reference < XBridgeFactory > rFactory( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory")), + OUString( RTL_CONSTASCII_USTRINGPARAM("bridgefac.uno" SAL_DLLEXTENSION)), + rSMgr ), + UNO_QUERY ); + + + MyThread threadAcceptor( rAcceptor , rFactory , OUString::createFromAscii( argv[1] ) ); + + threadAcceptor.create(); + TimeValue value={2,0}; + osl_waitThread( &value ); + + try + { + Reference < XConnection > rConnection = + rConnector->connect( OUString::createFromAscii( argv[1] ) ); + + printf( "%s\n" , OUStringToOString( rConnection->getDescription(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + + if( rFactory.is() ) + { + + Reference < XBridge > rBridge = rFactory->createBridge( + OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")), + OUString( RTL_CONSTASCII_USTRINGPARAM("iiop")), + rConnection, + Reference < XInstanceProvider > () ); + + Reference < XInterface > rInitialObject + = rBridge->getInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("bla")) ); + + if( rInitialObject.is() ) + { + printf( "got the remote object\n" ); + testRemote( rInitialObject ); + } + printf( "Closing...\n" ); + TimeValue timeValue={2,0}; + osl_waitThread( &timeValue ); + } + + Reference < XBridge > rBridge = rFactory->getBridge( + OUString( RTL_CONSTASCII_USTRINGPARAM("bla blub")) ); + OSL_ASSERT( ! rBridge.is() ); + + } + catch( Exception & ) + { + printf( "Login failed, got an Exception !\n" ); + } + + rAcceptor->stopAccepting(); + threadAcceptor.join(); + + Reference < XComponent > rComp( rFactory , UNO_QUERY ); + rComp->dispose(); + + + rComp = Reference < XComponent > ( rSMgr , UNO_QUERY ); + rComp->dispose(); + } + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/test/testserver.cxx b/bridges/test/testserver.cxx new file mode 100644 index 000000000000..fe85514872dd --- /dev/null +++ b/bridges/test/testserver.cxx @@ -0,0 +1,256 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" +#include <string.h> +#include <osl/time.h> + +#include <osl/mutex.hxx> +#include <osl/conditn.h> + +#include <osl/thread.hxx> + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/implbase1.hxx> + +#include <com/sun/star/connection/XAcceptor.hpp> +#include <com/sun/star/connection/XConnection.hpp> + +#include <com/sun/star/bridge/XInstanceProvider.hpp> +#include <com/sun/star/bridge/XBridgeFactory.hpp> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> + + +#include <test/XTestFactory.hpp> + +#include <cppuhelper/weak.hxx> + +using namespace ::test; +using namespace ::rtl; +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::connection; +#include "testcomp.h" +#ifdef SAL_W32 +#include <conio.h> +#endif + +/********* + * + ********/ + + + +class MyThread : + public Thread +{ +public: + MyThread( const Reference< XAcceptor > &r , + const Reference< XBridgeFactory > &rFactory, + const Reference< XMultiServiceFactory > &rSMgr, + const OUString &sConnectionDescription, + const OUString &sProtocol, + sal_Bool bReverse, + sal_Bool bLatency ) : + m_rAcceptor( r ), + m_rBridgeFactory ( rFactory ), + m_rSMgr( rSMgr ), + m_sConnectionDescription( sConnectionDescription ), + m_sProtocol( sProtocol ), + m_bReverse( bReverse ), + m_bLatency( bLatency ) + {} + virtual void SAL_CALL run(); + + void latencyTest( const Reference< XConnection > &r ); + +private: + Reference < XAcceptor > m_rAcceptor; + Reference < XBridgeFactory > m_rBridgeFactory; + Reference < XMultiServiceFactory > m_rSMgr; + OUString m_sConnectionDescription; + OUString m_sProtocol; + sal_Bool m_bReverse; + sal_Bool m_bLatency; +}; + + +void MyThread::latencyTest( const Reference< XConnection > &r ) +{ + Sequence < sal_Int8 > s; + while( 12 == r->read( s , 12 ) ) + { + r->read( s , 188 ); + s = Sequence < sal_Int8 >(60); + r->write( s ); + } +} + +void MyThread::run() +{ + + while ( sal_True ) + { + try + { + Reference < XConnection > rConnection = + m_rAcceptor->accept( m_sConnectionDescription ); + + if( ! rConnection.is() ) + { + break; + } + if( m_bLatency ) + { + latencyTest( rConnection ); + } + else + { + + Reference < XBridge > rBridge = + m_rBridgeFactory->createBridge( + OUString() , + m_sProtocol, + rConnection , + (XInstanceProvider * ) new OInstanceProvider(m_rSMgr) ); + + + if( m_bReverse ) + { + printf( "doing reverse callme test (test is ok, when on each line a +- appears\n" ); + Reference < XInterface > r = rBridge->getInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("blubber" ))); + Reference < XTestFactory > rFactory( r , UNO_QUERY ); + Reference < XCallMe > rCallMe = rFactory->createCallMe(); + + for( sal_Int32 i = 0 ; i < 1 ; i ++ ) + { + rCallMe->callOneway( + OUString( RTL_CONSTASCII_USTRINGPARAM("my test string")) , 2 ); + } + printf( "all oneway are send\n" ); + rCallMe->call( OUString( RTL_CONSTASCII_USTRINGPARAM( "reverse call me test finished" )) , 0 ); + printf( "revers callme test finished\n" ); + } + } + } + catch ( Exception & e ) + { + printf( "Exception was thrown by acceptor \n" ); + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + break; + } + catch ( ... ) + { + printf( "Exception was thrown by acceptor thread\n" ); + break; + } + } +} + + +int main( int argc, char *argv[] ) +{ +// testserver(); + + if( argc < 2 ) + { + printf( "usage : testserver [-r] connectionstring\n" + " -r does a reverse test (server calls client)\n" ); + return 0; + } + + OUString sConnectionString; + OUString sProtocol; + sal_Bool bReverse = sal_False; + sal_Bool bLatency = sal_False; + + parseCommandLine( argv , &sConnectionString , &sProtocol , &bLatency , &bReverse ); + + { + Reference< XMultiServiceFactory > rSMgr = createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM( "server.rdb" ) ) ); + + Reference < XBridgeFactory > rBridgeFactory ( createComponent( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory")), + OUString( RTL_CONSTASCII_USTRINGPARAM("bridgefac.uno" SAL_DLLEXTENSION )), + rSMgr ), + UNO_QUERY ); + + + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.Bridge.iiop")), + OUString( RTL_CONSTASCII_USTRINGPARAM("remotebridge.uno" SAL_DLLEXTENSION)), + rSMgr ); + + + Reference < XAcceptor > rAcceptor( + createComponent( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Acceptor")), + OUString( RTL_CONSTASCII_USTRINGPARAM("acceptor.uno" SAL_DLLEXTENSION)), + rSMgr ) , + UNO_QUERY ); + + MyThread thread( rAcceptor , + rBridgeFactory, + rSMgr, + sConnectionString, + sProtocol, + bReverse, + bLatency); + thread.create(); + +#ifdef SAL_W32 + _getch(); +#elif SOLARIS + getchar(); +#elif LINUX + TimeValue value={360,0}; + osl_waitThread( &value ); +#endif + printf( "Closing...\n" ); + + rAcceptor->stopAccepting(); + thread.join(); + + printf( "Closed\n" ); + + Reference < XComponent > rComp2( rBridgeFactory , UNO_QUERY ); + rComp2->dispose(); + Reference < XComponent > rComp( rSMgr, UNO_QUERY ); + rComp->dispose(); + } + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/unotypes/makefile.mk b/bridges/unotypes/makefile.mk new file mode 100644 index 000000000000..d5b3bc970e51 --- /dev/null +++ b/bridges/unotypes/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=.. + +PRJNAME=bridges +TARGET=unotypes + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +#------------------------------------------------------------------- + +CPPUMAKERFLAGS += -C +UNOUCRDEP=$(SOLARBINDIR)$/udkapi.rdb +UNOUCRRDB=$(SOLARBINDIR)$/udkapi.rdb +UNOUCROUT=$(OUT)$/inc + +UNOTYPES = \ + com.sun.star.uno.XInterface \ + com.sun.star.uno.TypeClass + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/version.mk b/bridges/version.mk new file mode 100644 index 000000000000..57c4c7f2a306 --- /dev/null +++ b/bridges/version.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# target +RMCXT_TARGET=rmcxt + +# the major +RMCXT_MAJOR=2 +# the minor +RMCXT_MINOR=0 +# the micro +RMCXT_MICRO=0 + +# this is a c++ compatible library +RMCXT_CPP=0 + |