diff options
Diffstat (limited to 'bridges')
312 files changed, 81007 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..82870cfd65c7 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/bridge.hxx @@ -0,0 +1,506 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: bridge.hxx,v $ + * $Revision: 1.16 $ + * + * 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_ + +#ifndef _BRIDGES_CPP_UNO_BRIDGE_H_ +#include <bridges/cpp_uno/bridge.h> +#endif +#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_ENSURE( 0, "### RuntimeException occured 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 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..15e66e48af8f --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/arraypointer.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: arraypointer.hxx,v $ + * $Revision: 1.4 $ + * + * 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 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..00f962cdeb38 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/bridge.hxx @@ -0,0 +1,131 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: bridge.hxx,v $ + * $Revision: 1.5 $ + * + * 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 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..aa85461761c0 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/cppinterfaceproxy.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cppinterfaceproxy.hxx,v $ + * $Revision: 1.6 $ + * + * 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 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..547d3c4d968c --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/types.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.hxx,v $ + * $Revision: 1.5 $ + * + * 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 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..e4a914acf8af --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/unointerfaceproxy.hxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: unointerfaceproxy.hxx,v $ + * $Revision: 1.5 $ + * + * 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 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..9d7fe10df838 --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx @@ -0,0 +1,217 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtablefactory.hxx,v $ + * $Revision: 1.7 $ + * + * 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 <hash_map> + +/*See: http://people.redhat.com/drepper/selinux-mem.html*/ +#ifdef LINUX +#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 std::hash_map< rtl::OUString, Vtables, rtl::OUStringHash > Map; + + osl::Mutex m_mutex; + Map m_map; + + rtl_arena_type * m_arena; +}; + +} } } + +#endif 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..f321af558c8d --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/shared/vtables.hxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtables.hxx,v $ + * $Revision: 1.4 $ + * + * 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 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..706bfa80af0a --- /dev/null +++ b/bridges/inc/bridges/cpp_uno/type_misc.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: type_misc.hxx,v $ + * $Revision: 1.6 $ + * + * 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 diff --git a/bridges/inc/bridges/remote/bridgeimpl.hxx b/bridges/inc/bridges/remote/bridgeimpl.hxx new file mode 100644 index 000000000000..2a0e867b8cc8 --- /dev/null +++ b/bridges/inc/bridges/remote/bridgeimpl.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: bridgeimpl.hxx,v $ + * $Revision: 1.5 $ + * + * 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_REMOTE_BRIDGEIMPL_HXX_ +#define _BRIDGES_REMOTE_BRIDGEIMPL_HXX_ +#include <osl/interlck.h> + +#include <uno/environment.h> + +#include <bridges/remote/context.h> +#include <bridges/remote/remote.h> + + +struct remote_BridgeImpl +{ + void (SAL_CALL * m_allThreadsAreGone ) ( uno_Environment * ); + requestClientSideDispatcher m_sendRequest; + oslInterlockedCount m_nRemoteThreads; + sal_Bool m_bDisposed; + sal_Bool m_bReleaseStubsCalled; +}; + +namespace bridges_remote { + + enum RemoteThreadCounter_HoldEnvWeak + { + RTC_HOLDENVWEAK = 0x1 + }; + + class RemoteThreadCounter + { + public: + // performance optimization. In some cases, it is not necessary to acquire the + // environment. + RemoteThreadCounter( uno_Environment *pEnvRemote, RemoteThreadCounter_HoldEnvWeak ) + : m_bReleaseEnvironment( sal_False ) + , m_pEnvRemote( pEnvRemote ) + { + remote_Context *pContext = ((remote_Context *) m_pEnvRemote->pContext ); + osl_incrementInterlockedCount( &( pContext->m_pBridgeImpl->m_nRemoteThreads ) ); + } + + RemoteThreadCounter( uno_Environment *pEnvRemote ) + : m_bReleaseEnvironment( sal_True ) + , m_pEnvRemote( pEnvRemote ) + { + m_pEnvRemote->acquire( m_pEnvRemote ); + + remote_Context *pContext = ((remote_Context *) m_pEnvRemote->pContext ); + osl_incrementInterlockedCount( &( pContext->m_pBridgeImpl->m_nRemoteThreads ) ); + } + + ~RemoteThreadCounter( ) + { + remote_Context *pContext = ((remote_Context *) m_pEnvRemote->pContext ); + if( 0 == osl_decrementInterlockedCount( &( pContext->m_pBridgeImpl->m_nRemoteThreads)) && + pContext->m_pBridgeImpl->m_bDisposed && + ! pContext->m_pBridgeImpl->m_bReleaseStubsCalled ) + { + pContext->m_pBridgeImpl->m_allThreadsAreGone( m_pEnvRemote ); + } + if( m_bReleaseEnvironment ) + m_pEnvRemote->release( m_pEnvRemote ); + } + + sal_Bool m_bReleaseEnvironment; + uno_Environment *m_pEnvRemote; + }; +} + +#endif diff --git a/bridges/inc/bridges/remote/connection.h b/bridges/inc/bridges/remote/connection.h new file mode 100644 index 000000000000..3c4dfe066c6f --- /dev/null +++ b/bridges/inc/bridges/remote/connection.h @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: connection.h,v $ + * $Revision: 1.4 $ + * + * 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_REMOTE_CONNECTION_H_ +#define _BRIDGES_REMOTE_CONNECTION_H_ +#include <sal/types.h> + +/** Specfies a C-interface for a bidirectional bytestream, + which is used by a UNO remote environment. + */ +struct remote_Connection +{ + void ( SAL_CALL * acquire ) ( remote_Connection *); + + void ( SAL_CALL * release ) ( remote_Connection *); + + /** + reads nSize bytes from the connection. This method blocks, until + all bytes are available or an error occurs. + @return Number of bytes read. + If the return value is less than nSize, an unrecoverable + i/o error has occured or the connection was closed. + + */ + sal_Int32 (SAL_CALL * read)(remote_Connection *, sal_Int8 *pDest, sal_Int32 nSize ); + + /** + @return Number of bytes written. + if the return value is less than nSize an unrecoverable + i/o error has occured or the connection was closed. + */ + sal_Int32 (SAL_CALL * write)(remote_Connection *, const sal_Int8 *pSource, sal_Int32 nSize ); + + void ( SAL_CALL * flush ) ( remote_Connection * ); + + /** closes the connection. + Any read or write operation after this call shall not be served + anymore. Any ongoing read or write operation must return immeadiatly after this call. + The implementation should cope with multiple calls to this method. + */ + void (SAL_CALL * close) ( remote_Connection * ); +}; + +#endif diff --git a/bridges/inc/bridges/remote/context.h b/bridges/inc/bridges/remote/context.h new file mode 100644 index 000000000000..e682c5230577 --- /dev/null +++ b/bridges/inc/bridges/remote/context.h @@ -0,0 +1,263 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: context.h,v $ + * $Revision: 1.8 $ + * + * 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_REMOTE_CONTEXT_H_ +#define _BRIDGES_REMOTE_CONTEXT_H_ +#include <osl/interlck.h> +#include <osl/conditn.h> + +#include <typelib/typedescription.h> + +#include <uno/environment.h> +#include <uno/any2.h> + + +/** Interface for refcounted contexts of uno-environments. + + Not all uno_Contexts need to be refcounted, in case they are, + they should be 'derived' from this struct. + This is used as a base class for the remote_Context. + @see uno_Environment + @see uno_getEnvironment() + @see remote_Context + */ +struct uno_Context +{ + /** increase the refcount of the context + */ + void (SAL_CALL * acquire)( uno_Context *pContext ); + + /** decrements the recount of the context. In case the recount drops to zero, + the context gets destroye. + */ + void (SAL_CALL * release)( uno_Context *pContext); + + /** Allows to query for a different interface of the uno_Context. + The result of the void pointer is unspecified and depends on the concrete context. + */ + void * (SAL_CALL *query ) ( uno_Context *pContext , rtl_uString *pId); +}; + +struct remote_Connection; +struct remote_Context; +struct remote_Interface; + + + +/** performs a query-interface for a certain interface via the remote connection ! + + @param pEnvRemote The environment, that shall perform the call. + @param ppRemoteI in/out parameter contains the interface returned by queryInterface + @param pOid the oid of the 'ghost' object on which the call must be done. + ***/ +typedef void ( SAL_CALL * remote_getInstanceFunc ) ( + uno_Environment *pEnvRemote, + remote_Interface **ppRemoteI, + rtl_uString *pOid, + typelib_TypeDescriptionReference *pInterfaceTypeRef, + uno_Any **ppException ); + + +/** refcounted C-interface, which provides object by name. + */ +struct remote_InstanceProvider +{ + void (SAL_CALL * acquire ) ( remote_InstanceProvider * pProvider ); + void (SAL_CALL * release ) ( remote_InstanceProvider * pProvider ); + void (SAL_CALL * getInstance ) ( remote_InstanceProvider * pProvider , + uno_Environment *pEnvRemote, + remote_Interface **ppRemoteI, + rtl_uString *pInstanceName, + typelib_InterfaceTypeDescription *pType, + uno_Any **ppException ); +}; + +/** refcounted C-interface, which allows to register a listener to an + remote bridge to be informed when the bridge gets disposed. + + @see remote_Context + */ +struct remote_DisposingListener +{ + void (SAL_CALL * acquire ) ( remote_DisposingListener * pProvider ); + void (SAL_CALL * release ) ( remote_DisposingListener * pProvider ); + void (SAL_CALL * disposing ) ( remote_DisposingListener * pProvider, + rtl_uString *pBridgeName ); +}; + + +/** + Try to get an existing context characterized by the pIdString. Each ID-String must + uniquely charcterize a certain connection. The context can't be retrieved via this + function anymore, after it got disposed. + + @return 0 when such a context does not exist, otherwise + a pointer to an acquired remote_Context. + **/ +extern "C" remote_Context * SAL_CALL +remote_getContext( rtl_uString *pIdString ); + +/** + Create an acquired remote context. The Context is weakly held by the context administration + and can be accessed later through remote_getContext() (using the same id-string). + + @param pIdString A string, that uniquely describes the connection. For e.g. a socket connection, + host and port of the local and remote host should be in the string. + + @param pDescription + Description of the connection, that may brought up to the user. + + @param pProtocol + The protocol, that the environment uses for + communicating with the remote process. + The format of the protocol string is : "protocolname,para1=para1value,..." + @return 0, when a context with this name already exists. + + @see remote_getContext() + @see remote_Context + */ +extern "C" remote_Context * SAL_CALL +remote_createContext( remote_Connection *pConnection, + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *); + +const sal_Int32 REMOTE_CONTEXT_CREATE = 1; +const sal_Int32 REMOTE_CONTEXT_DESTROY = 2; + +typedef void ( SAL_CALL * remote_contextListenerFunc ) ( + void *pThis, + sal_Int32 nRemoteContextMode, + rtl_uString *sName, + rtl_uString *sDescription + ); + +/** Registers a listener at the context administration, which allows to keep + track of existing remote connections. + @param pObject object which is handed to the listener function, when called. + */ +extern "C" void SAL_CALL +remote_addContextListener( remote_contextListenerFunc listener, void *pObject ); + + +/** Removes a listener from the context administration. + */ +extern "C" void SAL_CALL +remote_removeContextListener( remote_contextListenerFunc listener , void *pObject ); + +/** Allows to retrieve all existing context strings. + + @param pnStringCount out parameter. Contains the number of rtl_uStrings in the array + @param memAlloc a memory allocation function for the array of pointers to rtl_uStrings + + @return array of rtl strings. The caller must call release on all rtl_uString s and must free + the pointer array. + */ +extern "C" rtl_uString ** SAL_CALL +remote_getContextList( + sal_Int32 *pnStringCount, + void * ( SAL_CALL * memAlloc ) ( sal_Size nBytesToAlloc ) ); + + +struct remote_BridgeImpl; + +/** The context structure for a remote bridge. + + @see uno_getEnvironment() + */ +struct remote_Context +{ + struct uno_Context aBase; + + /** + These methods are implemented by context administration + */ + void ( SAL_CALL * addDisposingListener ) ( remote_Context *, + remote_DisposingListener * ); + void ( SAL_CALL * removeDisposingListener ) ( remote_Context *, + remote_DisposingListener * ); + /** + will be called by the environment when it gets disposed + */ + void ( SAL_CALL * dispose ) ( remote_Context * ); + + /** The method is set by the remote-environment during environment initialization. + @see remote_getInstanceFunc + */ + remote_getInstanceFunc getRemoteInstance; + + /** + The protocol, that the environment uses for communicating with the remote process. + The format of the protocol string is : "protocolname,para1=para1value,..." + The parameters are protocol dependend + */ + rtl_uString *m_pProtocol; + + /** + It may be the same as m_pName. + Livetime is handled by the context administration. + */ + rtl_uString *m_pDescription; + + /** + The name of this context at context administration. + A string, that uniquely describes this environment. + Livetime is handled by the context administration. + */ + rtl_uString *m_pName; + + /** The instance-provider, which is used to look up unknown object identifiers. + Is usually called on server side, when the first client request comes in. + Maybe 0. Livetime is handled by the context administration. + */ + remote_InstanceProvider *m_pInstanceProvider; + + /** + The connection of this context. + Livetime is handled by the context administration. + */ + remote_Connection *m_pConnection; + + /** + Here arbitrary data may be stored. It may be used by a connection + service to store environment specific data. The bridge does not + use it. + */ + void *m_pAdditionalInformation; + + /** + here the bridge stores its private per environment data. + */ + struct remote_BridgeImpl *m_pBridgeImpl; +}; + +#endif + diff --git a/bridges/inc/bridges/remote/counter.hxx b/bridges/inc/bridges/remote/counter.hxx new file mode 100644 index 000000000000..939c8b4967de --- /dev/null +++ b/bridges/inc/bridges/remote/counter.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: counter.hxx,v $ + * $Revision: 1.6 $ + * + * 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_REMOTE_COUNTER_H_ +#define _BRIDGES_REMOTE_COUNTER_H_ +#include <stdio.h> +#if OSL_DEBUG_LEVEL > 1 +struct MyCounter +{ + MyCounter( sal_Char const *pName ) : + m_nCounter( 0 ), + m_pName ( pName ) + { + } + ~MyCounter() + { + if( m_nCounter ) { + printf( + "%s : %ld left\n", m_pName, + sal::static_int_cast< long >(m_nCounter) ); + } + } + void acquire() + { m_nCounter ++; } + void release() + { m_nCounter --; } + + + sal_Int32 m_nCounter; + sal_Char const *m_pName; +}; +#endif + +#endif diff --git a/bridges/inc/bridges/remote/helper.hxx b/bridges/inc/bridges/remote/helper.hxx new file mode 100644 index 000000000000..ea2a98e74055 --- /dev/null +++ b/bridges/inc/bridges/remote/helper.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: helper.hxx,v $ + * $Revision: 1.5 $ + * + * 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 <bridges/remote/bridgeimpl.hxx> + +typedef void ( SAL_CALL * ReleaseRemoteCallbackFunc ) ( + remote_Interface *ppRemoteI, + rtl_uString *pOid, + typelib_TypeDescriptionReference *pTypeRef, + uno_Environment *pEnvRemote + ); + +typedef void ( SAL_CALL * remote_createStubFunc ) ( + remote_Interface **ppRemoteI, + rtl_uString *pOid , + typelib_TypeDescriptionReference *pTypeRef, + uno_Environment *pEnvRemote, + ReleaseRemoteCallbackFunc callback + ); +namespace bridges_remote +{ + + /** @param callback If the bridge implementation wants to handle the remote release call, + it can do it giving this callback. If callback == 0, the releaseRemote + method of the stub is called. + */ + void SAL_CALL remote_createStub ( + remote_Interface **ppRemoteI, + rtl_uString *pOid , + typelib_TypeDescriptionReference *pType, + uno_Environment *pEnvRemote, + ReleaseRemoteCallbackFunc callback ); + + void SAL_CALL remote_retrieveOidFromProxy( + remote_Interface *pRemtoeI, + rtl_uString **ppOid ); + + void SAL_CALL remote_sendQueryInterface( + uno_Environment *pEnvRemote, + remote_Interface **ppRemoteI, + rtl_uString *pOid , + typelib_TypeDescriptionReference *pType, + uno_Any **ppException + ); +} diff --git a/bridges/inc/bridges/remote/mapping.hxx b/bridges/inc/bridges/remote/mapping.hxx new file mode 100644 index 000000000000..42577db07d0e --- /dev/null +++ b/bridges/inc/bridges/remote/mapping.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: mapping.hxx,v $ + * $Revision: 1.4 $ + * + * 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_REMOTE_MAPPING_HXX_ +#define _BRIDGES_REMOTE_MAPPING_HXX_ + +#include <osl/interlck.h> +#include <rtl/ustring.hxx> + +#include <typelib/typedescription.h> + +#include <bridges/remote/remote.h> + +typedef struct _uno_Environment uno_Environment; + +namespace bridges_remote +{ + extern "C" typedef void SAL_CALL RemoteToUno( + uno_Mapping *pMapping, void **ppOut, void *pInterface, + typelib_InterfaceTypeDescription *pInterfaceTypeDescr ); + RemoteToUno remoteToUno; + + extern "C" typedef void SAL_CALL UnoToRemote( + uno_Mapping *pMapping, void **ppOut, void *pInterface, + typelib_InterfaceTypeDescription *pInterfaceTypeDescr ); + UnoToRemote unoToRemote; + + extern "C" typedef void SAL_CALL FreeRemoteMapping(uno_Mapping * mapping); + FreeRemoteMapping freeRemoteMapping; + + class RemoteMapping : + public remote_Mapping + { + public: + RemoteMapping( uno_Environment *pEnvUno , + uno_Environment *pEnvRemote, + uno_MapInterfaceFunc func , + const ::rtl::OUString sPurpose); + ~RemoteMapping(); + + oslInterlockedCount m_nRef; + ::rtl::OUString m_sPurpose; + }; + +} +#endif diff --git a/bridges/inc/bridges/remote/proxy.hxx b/bridges/inc/bridges/remote/proxy.hxx new file mode 100644 index 000000000000..03e2f8684c48 --- /dev/null +++ b/bridges/inc/bridges/remote/proxy.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: proxy.hxx,v $ + * $Revision: 1.4 $ + * + * 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 <osl/interlck.h> + +#include <uno/environment.h> +#include <uno/dispatcher.h> +#include <uno/mapping.hxx> + +#include <bridges/remote/remote.h> + +namespace bridges_remote { + +extern "C" typedef void SAL_CALL FreeRemote2UnoProxy( + uno_ExtEnvironment * environment, void * proxy); +FreeRemote2UnoProxy freeRemote2UnoProxy; + +// private: +extern "C" typedef void SAL_CALL AcquireRemote2UnoProxy(uno_Interface *); +AcquireRemote2UnoProxy acquireRemote2UnoProxy; + +// private: +extern "C" typedef void SAL_CALL ReleaseRemote2UnoProxy(uno_Interface *); +ReleaseRemote2UnoProxy releaseRemote2UnoProxy; + +// private: +extern "C" typedef void SAL_CALL DispatchRemote2UnoProxy( + uno_Interface *, typelib_TypeDescription const *, void *, void **, + uno_Any **); +DispatchRemote2UnoProxy dispatchRemote2UnoProxy; + +extern "C" void SAL_CALL remote_release( void * ); + +class Remote2UnoProxy : + public uno_Interface +{ +public: + Remote2UnoProxy( + remote_Interface *pRemoteI, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType , + uno_Environment *pEnvUno, + uno_Environment *pEnvRemote + ); + + ~Remote2UnoProxy(); + +private: + ::rtl::OUString m_sOid; + typelib_InterfaceTypeDescription *m_pType; + remote_Interface *m_pRemoteI; + uno_Environment *m_pEnvUno; + uno_Environment *m_pEnvRemote; + ::com::sun::star::uno::Mapping m_mapRemote2Uno; + ::com::sun::star::uno::Mapping m_mapUno2Remote; + + oslInterlockedCount m_nRef; + + friend void SAL_CALL acquireRemote2UnoProxy(uno_Interface *); + + friend void SAL_CALL releaseRemote2UnoProxy(uno_Interface *); + + friend void SAL_CALL dispatchRemote2UnoProxy( + uno_Interface *, typelib_TypeDescription const *, void *, void **, + uno_Any **); +}; + +} diff --git a/bridges/inc/bridges/remote/remote.h b/bridges/inc/bridges/remote/remote.h new file mode 100644 index 000000000000..00fd8f5e778d --- /dev/null +++ b/bridges/inc/bridges/remote/remote.h @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: remote.h,v $ + * $Revision: 1.7 $ + * + * 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_REMOTE_REMOTE_H +#define _BRIDGES_REMOTE_REMOTE_H +#include <uno/mapping.h> +#include <uno/any2.h> + +#include <typelib/typedescription.h> +#include <uno/environment.h> + +#define CORBA_STRING8_NAME "com.sun.star.corba.CorbaString8" +#define CORBA_STRING8_NAME_LENGTH (sizeof(CORBA_STRING8_NAME)-1) + +#define CORBA_UNION_NAME "com.sun.star.corba.CorbaUnion" +#define CORBA_UNION_NAME_LENGTH (sizeof(CORBA_UNION_NAME)-1) + +#define REMOTE_MARSHALED_MSGHDR_SIZE 12 +#define REMOTE_RELEASE_METHOD_INDEX 2 +#define REMOTE_RELEASE_METHOD_NAME "release" + +#define CURRENT_IIOP_PROTOCOL_MAJOR 1 +#define CURRENT_IIOP_PROTOCOL_MINOR 2 + +extern "C" { + +struct remote_Interface; + +/** @internal + */ +typedef void (SAL_CALL * remote_DispatchMethod)( + remote_Interface * pRemoteI, typelib_TypeDescription const * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ); + +/** + @internal + */ +typedef void ( SAL_CALL * requestClientSideDispatcher ) ( + uno_Environment *pEnvRemote, + typelib_TypeDescription const * pMemberType, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException ); + +/** The base class of an UNO interface in a remote environment. + */ +struct remote_Interface +{ + void (SAL_CALL * acquire)( remote_Interface * pInterface ); + + void (SAL_CALL * release)( remote_Interface * pInterface ); + + remote_DispatchMethod pDispatcher; +}; + +/** The mapping between an binary-c-uno and a remote environment. + @internal + */ +struct remote_Mapping +{ + uno_Mapping aBase; + uno_Environment *pEnvRemote; + uno_Environment *pEnvUno; +}; + +} + +#endif diff --git a/bridges/inc/bridges/remote/remote.hxx b/bridges/inc/bridges/remote/remote.hxx new file mode 100644 index 000000000000..c9d6fd08cbc1 --- /dev/null +++ b/bridges/inc/bridges/remote/remote.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: remote.hxx,v $ + * $Revision: 1.7 $ + * + * 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_REMOTE_REMOTE_HXX_ +#define _BRIDGES_REMOTE_REMOTE_HXX_ +#include <list> + +#include <osl/mutex.hxx> +#include <osl/conditn.h> +#include <osl/interlck.h> + +#include <uno/environment.h> + +#include <bridges/remote/remote.h> +#include <bridges/remote/connection.h> + +#include <com/sun/star/uno/Sequence.hxx> + +namespace bridges_remote { + +extern "C" typedef void SAL_CALL AcquireRemote2RemoteStub( + remote_Interface * pThis); +AcquireRemote2RemoteStub acquireRemote2RemoteStub; + +extern "C" typedef void SAL_CALL FreeRemote2RemoteStub( + uno_ExtEnvironment * environment, void * stub); +FreeRemote2RemoteStub freeRemote2RemoteStub; + +class Remote2RemoteStub : + public remote_Interface +{ +public: + Remote2RemoteStub(rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType, + uno_Environment *pEnvRemote, + requestClientSideDispatcher dispatch ); + ~Remote2RemoteStub(); + + void releaseRemote(); +public: + ::rtl::OUString m_sOid; + typelib_InterfaceTypeDescription *m_pType; + oslInterlockedCount m_nRef; + uno_Environment *m_pEnvRemote; + requestClientSideDispatcher m_dispatch; + oslInterlockedCount m_nReleaseRemote; +}; + +} +#endif diff --git a/bridges/inc/bridges/remote/stub.hxx b/bridges/inc/bridges/remote/stub.hxx new file mode 100644 index 000000000000..5f97270aac6b --- /dev/null +++ b/bridges/inc/bridges/remote/stub.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: stub.hxx,v $ + * $Revision: 1.4 $ + * + * 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 <bridges/remote/remote.hxx> + +#include <uno/dispatcher.h> +#include <uno/mapping.hxx> + +namespace bridges_remote { + +extern "C" typedef void SAL_CALL AcquireUno2RemoteStub( remote_Interface *pThis ); +AcquireUno2RemoteStub acquireUno2RemoteStub; + +extern "C" typedef void SAL_CALL FreeUno2RemoteStub( + uno_ExtEnvironment * environment, void * stub); +FreeUno2RemoteStub freeUno2RemoteStub; + +class Uno2RemoteStub : + public remote_Interface +{ +public: + Uno2RemoteStub( uno_Interface *pUnoI, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType, + uno_Environment *pEnvUno, + uno_Environment *pEnvRemote ); + ~Uno2RemoteStub(); + +public: + ::rtl::OUString m_sOid; + typelib_InterfaceTypeDescription *m_pType; + uno_Interface *m_pUnoI; + oslInterlockedCount m_nRef; + + uno_Environment *m_pEnvUno; + uno_Environment *m_pEnvRemote; + ::com::sun::star::uno::Mapping m_mapRemote2Uno; + ::com::sun::star::uno::Mapping m_mapUno2Remote; +}; + +} diff --git a/bridges/inc/makefile.mk b/bridges/inc/makefile.mk new file mode 100644 index 000000000000..a6000d891c9d --- /dev/null +++ b/bridges/inc/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.3 $ +# +# 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..57d9cfff502d --- /dev/null +++ b/bridges/inc/pch/precompiled_bridges.cxx @@ -0,0 +1,32 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: precompiled_bridges.cxx,v $ + * $Revision: 1.3 $ + * + * 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" + diff --git a/bridges/inc/pch/precompiled_bridges.hxx b/bridges/inc/pch/precompiled_bridges.hxx new file mode 100644 index 000000000000..aa906d851972 --- /dev/null +++ b/bridges/inc/pch/precompiled_bridges.hxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: precompiled_bridges.hxx,v $ + * $Revision: 1.4 $ + * + * 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/XProtocolProperties.hdl" +#include "com/sun/star/bridge/XProtocolProperties.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/DisposedException.hdl" +#include "com/sun/star/lang/DisposedException.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 diff --git a/bridges/prj/build.lst b/bridges/prj/build.lst new file mode 100644 index 000000000000..c6e342520672 --- /dev/null +++ b/bridges/prj/build.lst @@ -0,0 +1,35 @@ +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\remote\static nmake - all br_rem_static br_unotypes br_inc NULL +br bridges\source\remote\urp nmake - all br_rem_urp br_rem_static br_inc NULL +br bridges\source\remote\context nmake - all br_rcon br_unotypes br_inc 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\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_freebsd_intel nmake - u br_gcc3fi 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_freebsd_x86-64 nmake - u br_gcc3fx br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_powerpc nmake - u br_gcclp3 br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_powerpc64 nmake - u br_gcclp3_64 br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_mips nmake - u br_gcc3mips br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_m68k nmake - u br_gcc3m68k br_cppuno_shared br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_s390 nmake - u br_gccl33 br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_s390x nmake - u br_gccl3x br_unotypes br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_sparc nmake - u br_gccl3s br_unotypes br_cppuno_shared br_inc NULL +br bridges\source\cpp_uno\gcc3_linux_arm nmake - u br_gccl3r br_unotypes NULL +br bridges\source\cpp_uno\gcc3_linux_ia64 nmake - u br_gccl3a br_unotypes NULL +br bridges\source\cpp_uno\gcc3_linux_hppa nmake - u br_gccl3h 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\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\gcc3_netbsd_intel nmake - u br_gccni 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..0b3dd93370d4 --- /dev/null +++ b/bridges/prj/d.lst @@ -0,0 +1,28 @@ +mkdir: %_DEST%\inc%_EXT%\bridges +mkdir: %_DEST%\inc%_EXT%\bridges\remote + +..\inc\bridges\remote\connection.h %_DEST%\inc%_EXT%\bridges\remote\connection.h +..\inc\bridges\remote\context.h %_DEST%\inc%_EXT%\bridges\remote\context.h +..\inc\bridges\remote\remote.h %_DEST%\inc%_EXT%\bridges\remote\remote.h + +..\%__SRC%\lib\irmcxt* %_DEST%\lib%_EXT%\* +..\%__SRC%\lib\librmcxt.*.* %_DEST%\lib%_EXT%\* +..\%__SRC%\bin\rmcxt*.dll %_DEST%\bin%_EXT%\* + +..\%__SRC%\lib\liburp_uno* %_DEST%\lib%_EXT%\liburp_uno* +..\%__SRC%\bin\urp_uno* %_DEST%\bin%_EXT%\urp_uno* +..\%__SRC%\lib\libjava_uno* %_DEST%\lib%_EXT%\libjava_uno* +..\%__SRC%\bin\java_uno* %_DEST%\bin%_EXT%\java_uno* +..\%__SRC%\class\java_uno*.jar %_DEST%\bin%_EXT%\java_uno*.jar + +..\%__SRC%\bin\msci_uno.* %_DEST%\bin%_EXT%\msci_uno.* +..\%__SRC%\bin\gcc3_uno.dll %_DEST%\bin%_EXT%\gcc3_uno.dll +..\%__SRC%\lib\libgcc2_uno.* %_DEST%\lib%_EXT%\libgcc2_uno.* +..\%__SRC%\lib\libgcc3_uno.* %_DEST%\lib%_EXT%\libgcc3_uno.* +..\%__SRC%\bin\gcc3_uno.* %_DEST%\bin%_EXT%\gcc3_uno.* +..\%__SRC%\lib\libsunpro5_uno.* %_DEST%\lib%_EXT%\libsunpro5_uno.* + +..\%__SRC%\lib\rmcxt3.lib %_DEST%\lib%_EXT%\rmcxt.lib + + +linklib: librmcxt.*.* 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..cdc13d106e0f --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/cc50_solaris_intel.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cc50_solaris_intel.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); +} + 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..c5b08cf2fee6 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/cpp2uno.cxx @@ -0,0 +1,530 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.17 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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 *) +{} 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..66a0d62cd66c --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/except.cxx @@ -0,0 +1,452 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.18 $ + * + * 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 +namespace rtl +{ + 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 rtl; +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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + return; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "> c++ exception occured: %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 ); +} + +} + 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..e7239d6dcb62 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/hash.cxx @@ -0,0 +1,266 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: hash.cxx,v $ + * $Revision: 1.4 $ + * + * 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 +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif +#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 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..9a18ecc8615f --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/makefile.mk @@ -0,0 +1,79 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.13 $ +# +# 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..8e439984bdb5 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_intel/uno2cpp.cxx @@ -0,0 +1,421 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.17 $ + * + * 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 rtl; +using namespace com::sun::star::uno; + +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 occured... + *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 ); + } + } +} + +} } } 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..ebd68f9e6616 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/cc50_solaris_sparc.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cc50_solaris_sparc.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); + +} + 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..05a0a304de27 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/cpp2uno.cxx @@ -0,0 +1,533 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.25 $ + * + * 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 occured... + 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 occured... + { + // 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!" ); +// if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) +// { +// RuntimeException aExc; +// aExc.Message = OUString::createFromAscii("illegal vtable index!"); +// aExc.Context = (XInterface *)pThis; +// throw aExc; +// } + + // 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; + } +// default: +// { +// RuntimeException aExc; +// aExc.Message = OUString::createFromAscii("no member description found!"); +// aExc.Context = (XInterface *)pThis; +// throw aExc; +// // is here for dummy +// eRet = typelib_TypeClass_VOID; +// } + } + + 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); +} 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..26f501505f78 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/except.cxx @@ -0,0 +1,448 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.18 $ + * + * 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 +namespace rtl +{ + 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 rtl; +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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + return; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "> c++ exception occured: %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 ); +} + +} + + + + 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..2945bd3648d6 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/flushcode.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: flushcode.hxx,v $ + * $Revision: 1.4.20.1 $ + * + * 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 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..0d3e4afe5e65 --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/hash.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: hash.cxx,v $ + * $Revision: 1.6 $ + * + * 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 +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif +#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 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..2e569d4f008f --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.17.12.1 $ +# +# 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" + +#CFLAGS += -O5 -xO5 + +.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..bfcf4607ce7d --- /dev/null +++ b/bridges/source/cpp_uno/cc50_solaris_sparc/uno2cpp.cxx @@ -0,0 +1,399 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.21 $ + * + * 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 rtl; +using namespace com::sun::star::uno; + +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 occured... + *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 ); + } + } +} + +} } } 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..d660e9b7dd94 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.hxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: callvirtualmethod.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 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..c680f092baeb --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/callvirtualmethod.s @@ -0,0 +1,63 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: callvirtualmethod.s,v $ + * + * $Revision: 1.3 $ + * + * 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..ad40d673513f --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx @@ -0,0 +1,615 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * + * $Revision: 1.5 $ + * + * 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); +} 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..ef56f2b05831 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.cxx @@ -0,0 +1,463 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: exceptions.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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); + } +} + +} } } 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..bdbbeee8afe6 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/exceptions.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: exceptions.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 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..ac87b8200c30 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/flushcode.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: flushcode.hxx,v $ + * + * $Revision: 1.3.18.1 $ + * + * 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 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..098cc1a116ee --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.hxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: fp.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 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..5ed11e3756e2 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/fp.s @@ -0,0 +1,606 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: fp.s,v $ + * + * $Revision: 1.3 $ + * + * 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..bb996e52eaff --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: isdirectreturntype.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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; + } + } +} + +} } } 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..5c405911c722 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/isdirectreturntype.hxx @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: isdirectreturntype.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 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..f1f98f32ca7d --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.4.12.1 $ +# +# 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..8921bea4330c --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/uno2cpp.cxx @@ -0,0 +1,513 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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; + } +} + +} } } 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..5e0a52be81dd --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.hxx @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtableslotcall.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 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..ffcbbec5be3f --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/vtableslotcall.s @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtableslotcall.s,v $ + * + * $Revision: 1.3 $ + * + * 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_freebsd_intel/call.s b/bridges/source/cpp_uno/gcc3_freebsd_intel/call.s new file mode 100644 index 000000000000..f345e3a764ac --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/call.s @@ -0,0 +1,268 @@ + .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 $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: + .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: + 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 + 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 $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: + .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 + 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 $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: + .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_freebsd_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_freebsd_intel/cpp2uno.cxx new file mode 100644 index 000000000000..c424b77ccd1b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/cpp2uno.cxx @@ -0,0 +1,493 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.12 $ + * + * 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 (bridges::cpp_uno::shared::isSimpleType( 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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_TypeClass returnTypeClass) +{ + if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass)) { + 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_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_INTERFACE: + 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); + 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->eTypeClass); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + typelib_TypeClass_VOID); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = codeSnippet( + code, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef->eTypeClass); + 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 *) +{} diff --git a/bridges/source/cpp_uno/gcc3_freebsd_intel/except.cxx b/bridges/source/cpp_uno/gcc3_freebsd_intel/except.cxx new file mode 100644 index 000000000000..cce600e964cf --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/except.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.9 $ + * + * 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 <hash_map> +#include <sys/param.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 hash_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 __FreeBSD_version < 602103 + : 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 __FreeBSD_version < 602103 /* #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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + diff --git a/bridges/source/cpp_uno/gcc3_freebsd_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_freebsd_intel/makefile.mk new file mode 100644 index 000000000000..cc10bdaf74be --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.9 $ +# +# 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)" == "GCCFREEBSDIgcc3" + +.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 + +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 +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(CC) -c -o $(SLO)$/$(@:b).o $< + touch $@ diff --git a/bridges/source/cpp_uno/gcc3_freebsd_intel/share.hxx b/bridges/source/cpp_uno/gcc3_freebsd_intel/share.hxx new file mode 100644 index 000000000000..1a171ffe08a2 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); +} diff --git a/bridges/source/cpp_uno/gcc3_freebsd_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_freebsd_intel/uno2cpp.cxx new file mode 100644 index 000000000000..514b41fb4a58 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_intel/uno2cpp.cxx @@ -0,0 +1,447 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.11 $ + * + * 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 <stdlib.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_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 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; + 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; + + // 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 + 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->eTypeClass, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occured... + *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 ); + } + } +} + +} } } diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.cxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.cxx new file mode 100644 index 000000000000..df2c51b67b5f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.cxx @@ -0,0 +1,806 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: abi.cxx,v $ + * $Revision: 1.4 $ + * + * 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; + +typedef struct +{ + /* Registers for argument passing. */ + long gpr[MAX_GPR_REGS]; + __int128_t sse[MAX_SSE_REGS]; + + /* Stack space for arguments. */ + char argspace[0]; +} stackLayout; + +/* 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 + +#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) + +/* 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 &rByteOffset ) +{ + /* First, align to the right place. */ + rByteOffset = ALIGN( rByteOffset, pTypeRef->pType->nAlignment ); + + 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 ( ( rByteOffset % 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 ( ( rByteOffset % 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 num = classify_argument( pTypeInStruct, subclasses, rByteOffset ); + + if ( num == 0 ) + { + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return 0; + } + + for ( int i = 0; i < num; i++ ) + { + int pos = rByteOffset / 8; + classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] ); + } + + if ( pTypeInStruct->eTypeClass != typelib_TypeClass_STRUCT ) + rByteOffset = pStruct->pMemberOffsets[ nMember ]; + } + + 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 offset = 0; + int n; + + n = classify_argument( pTypeRef, classes, offset ); + + 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, void * const *pGPR, void * const *pSSE, void *pStruct ) +{ + enum x86_64_reg_class classes[MAX_CLASSES]; + int offset = 0; + int n; + + n = classify_argument( pTypeRef, classes, offset ); + + 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++ = *reinterpret_cast<sal_uInt64 *>( *pGPR++ ); + break; + case X86_64_SSE_CLASS: + case X86_64_SSESF_CLASS: + case X86_64_SSEDF_CLASS: + *pStructAlign++ = *reinterpret_cast<sal_uInt64 *>( *pSSE++ ); + break; + } +} + +#if 0 + +/* Functions to load floats and double to an SSE register placeholder. */ +extern void float2sse (float, __int128_t *); +extern void double2sse (double, __int128_t *); +extern void floatfloat2sse (void *, __int128_t *); + +/* Functions to put the floats and doubles back. */ +extern float sse2float (__int128_t *); +extern double sse2double (__int128_t *); +extern void sse2floatfloat(__int128_t *, void *); + +/*@-exportheader@*/ +void +ffi_prep_args (stackLayout *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ + int gprcount, ssecount, i, g, s; + void **p_argv; + void *argp = &stack->argspace; + ffi_type **p_arg; + + /* First check if the return value should be passed in memory. If so, + pass the pointer as the first argument. */ + gprcount = ssecount = 0; + if (ecif->cif->rtype->type != FFI_TYPE_VOID + && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0) + (void *)stack->gpr[gprcount++] = ecif->rvalue; + + for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue; + i!=0; i--, p_arg++, p_argv++) + { + int in_register = 0; + + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_UINT32: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + if (gprcount < MAX_GPR_REGS) + { + stack->gpr[gprcount] = 0; + stack->gpr[gprcount++] = *(long long *)(*p_argv); + in_register = 1; + } + break; + + case FFI_TYPE_FLOAT: + if (ssecount < MAX_SSE_REGS) + { + float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]); + in_register = 1; + } + break; + + case FFI_TYPE_DOUBLE: + if (ssecount < MAX_SSE_REGS) + { + double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]); + in_register = 1; + } + break; + } + + if (in_register) + continue; + + /* Either all places in registers where filled, or this is a + type that potentially goes into a memory slot. */ + if (examine_argument (*p_arg, 0, &g, &s) == 0 + || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) + { + /* Pass this argument in memory. */ + argp = (void *)ALIGN(argp, (*p_arg)->alignment); + memcpy (argp, *p_argv, (*p_arg)->size); + argp += (*p_arg)->size; + } + else + { + /* All easy cases are eliminated. Now fire the big guns. */ + + enum x86_64_reg_class classes[MAX_CLASSES]; + int offset = 0, j, num; + void *a; + + num = classify_argument (*p_arg, classes, &offset); + for (j=0, a=*p_argv; j<num; j++, a+=8) + { + switch (classes[j]) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + stack->gpr[gprcount++] = *(long long *)a; + break; + case X86_64_SSE_CLASS: + floatfloat2sse (a, &stack->sse[ssecount++]); + break; + case X86_64_SSESF_CLASS: + float2sse (*(float *)a, &stack->sse[ssecount++]); + break; + case X86_64_SSEDF_CLASS: + double2sse (*(double *)a, &stack->sse[ssecount++]); + break; + default: + abort(); + } + } + } + } +} + +/* Perform machine dependent cif processing. */ +ffi_status +ffi_prep_cif_machdep (ffi_cif *cif) +{ + int gprcount, ssecount, i, g, s; + + gprcount = ssecount = 0; + + /* Reset the byte count. We handle this size estimation here. */ + cif->bytes = 0; + + /* If the return value should be passed in memory, pass the pointer + as the first argument. The actual memory isn't allocated here. */ + if (cif->rtype->type != FFI_TYPE_VOID + && examine_argument (cif->rtype, 1, &g, &s) == 0) + gprcount = 1; + + /* Go over all arguments and determine the way they should be passed. + If it's in a register and there is space for it, let that be so. If + not, add it's size to the stack byte count. */ + for (i=0; i<cif->nargs; i++) + { + if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0 + || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) + { + /* This is passed in memory. First align to the basic type. */ + cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment); + + /* Stack arguments are *always* at least 8 byte aligned. */ + cif->bytes = ALIGN(cif->bytes, 8); + + /* Now add the size of this argument. */ + cif->bytes += cif->arg_types[i]->size; + } + else + { + gprcount += g; + ssecount += s; + } + } + + /* Set the flag for the closures return. */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + case FFI_TYPE_SINT64: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + cif->flags = (unsigned) cif->rtype->type; + break; + + case FFI_TYPE_UINT64: + cif->flags = FFI_TYPE_SINT64; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +typedef struct +{ + long gpr[2]; + __int128_t sse[2]; + long double st0; +} return_value; + +//#endif + +void +ffi_fill_return_value (return_value *rv, extended_cif *ecif) +{ + enum x86_64_reg_class classes[MAX_CLASSES]; + int i = 0, num; + long *gpr = rv->gpr; + __int128_t *sse = rv->sse; + signed char sc; + signed short ss; + + /* This is needed because of the way x86-64 handles signed short + integers. */ + switch (ecif->cif->rtype->type) + { + case FFI_TYPE_SINT8: + sc = *(signed char *)gpr; + *(long long *)ecif->rvalue = (long long)sc; + return; + case FFI_TYPE_SINT16: + ss = *(signed short *)gpr; + *(long long *)ecif->rvalue = (long long)ss; + return; + default: + /* Just continue. */ + ; + } + + num = classify_argument (ecif->cif->rtype, classes, &i); + + if (num == 0) + /* Return in memory. */ + ecif->rvalue = (void *) rv->gpr[0]; + else if (num == 2 && classes[0] == X86_64_X87_CLASS && + classes[1] == X86_64_X87UP_CLASS) + /* This is a long double (this is easiest to handle this way instead + of an eightbyte at a time as in the loop below. */ + *((long double *)ecif->rvalue) = rv->st0; + else + { + void *a; + + for (i=0, a=ecif->rvalue; i<num; i++, a+=8) + { + switch (classes[i]) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + *(long long *)a = *gpr; + gpr++; + break; + case X86_64_SSE_CLASS: + sse2floatfloat (sse++, a); + break; + case X86_64_SSESF_CLASS: + *(float *)a = sse2float (sse++); + break; + case X86_64_SSEDF_CLASS: + *(double *)a = sse2double (sse++); + break; + default: + abort(); + } + } + } +} + +//#if 0 + +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *), + void (*) (return_value *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, /*@out@*/ unsigned *, void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ + +void ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue) +{ + extended_cif ecif; + int dummy; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + /* Stack must always be 16byte aligned. Make it so. */ + cif->bytes = ALIGN(cif->bytes, 16); + + switch (cif->abi) + { + case FFI_SYSV: + /* Calling 32bit code from 64bit is not possible */ + FFI_ASSERT(0); + break; + + case FFI_UNIX64: + /*@-usedef@*/ + ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif, + cif->bytes, ecif.rvalue, fn); + /*@=usedef@*/ + break; + + default: + FFI_ASSERT(0); + break; + } +} + +extern void ffi_closure_UNIX64(void); + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data) +{ + volatile unsigned short *tramp; + + /* FFI_ASSERT (cif->abi == FFI_OSF); */ + + tramp = (volatile unsigned short *) &closure->tramp[0]; + tramp[0] = 0xbb49; /* mov <code>, %r11 */ + tramp[5] = 0xba49; /* mov <data>, %r10 */ + tramp[10] = 0xff49; /* jmp *%r11 */ + tramp[11] = 0x00e3; + *(void * volatile *) &tramp[1] = ffi_closure_UNIX64; + *(void * volatile *) &tramp[6] = closure; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + return FFI_OK; +} + +int +ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp) +{ + ffi_cif *cif; + void **avalue; + ffi_type **arg_types; + long i, avn, argn; + + cif = closure->cif; + avalue = alloca(cif->nargs * sizeof(void *)); + + argn = 0; + + i = 0; + avn = cif->nargs; + arg_types = cif->arg_types; + + /* Grab the addresses of the arguments from the stack frame. */ + while (i < avn) + { + switch (arg_types[i]->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + { + if (l->gp_offset > 48-8) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->gp_offset; + l->gp_offset += 8; + } + } + break; + + case FFI_TYPE_STRUCT: + /* FIXME */ + FFI_ASSERT(0); + break; + + case FFI_TYPE_DOUBLE: + { + if (l->fp_offset > 176-16) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->fp_offset; + l->fp_offset += 16; + } + } +#if DEBUG_FFI + fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]); +#endif + break; + + case FFI_TYPE_FLOAT: + { + if (l->fp_offset > 176-16) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->fp_offset; + l->fp_offset += 16; + } + } +#if DEBUG_FFI + fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]); +#endif + break; + + default: + FFI_ASSERT(0); + } + + argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG; + i++; + } + + /* Invoke the closure. */ + (closure->fun) (cif, rp, avalue, closure->user_data); + + /* FIXME: Structs not supported. */ + FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT); + + /* Tell ffi_closure_UNIX64 how to perform return type promotions. */ + + return cif->rtype->type; +} + +#endif diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.hxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.hxx new file mode 100644 index 000000000000..5fffe680c28a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: abi.hxx,v $ + * $Revision: 1.3 $ + * + * 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, void * const *pGPR, void * const *pSSE, void *pStruct ); + +} // namespace x86_64 + +#endif // _BRIDGES_CPP_UNO_X86_64_ABI_HXX_ diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/call.s b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/call.s new file mode 100644 index 000000000000..736230705d5a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/call.s @@ -0,0 +1,93 @@ + .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) + 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_freebsd_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/cpp2uno.cxx new file mode 100644 index 000000000000..9b326ff34b0d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/cpp2uno.cxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 */ ) +{ + int nr_gpr = 0; //number of gpr registers used + int nr_fpr = 0; //number of fpr regsiters 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]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + int nUsedGPR = 0; + int nUsedSSE = 0; + bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE ); + if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ) ) // 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++; + } + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // struct <= 16 bytes || ptr to complex value || ref + { + void *pCppStack; + char pTmpStruct[16]; + + if ( bFitsRegisters && !rParam.bOut && + ( pParamTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || + pParamTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION ) ) + { + if ( ( nr_gpr + nUsedGPR <= x86_64::MAX_GPR_REGS ) && ( nr_fpr + nUsedSSE <= x86_64::MAX_SSE_REGS ) ) + { + x86_64::fill_struct( rParam.pTypeRef, gpreg, fpreg, pTmpStruct ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "nUsedGPR == %d, nUsedSSE == %d, pTmpStruct[0] == 0x%x, pTmpStruct[1] == 0x%x, **gpreg == 0x%lx\n", + nUsedGPR, nUsedSSE, pTmpStruct[0], pTmpStruct[1], *(sal_uInt64*)*gpreg ); +#endif + + pCppArgs[nPos] = pCppStack = reinterpret_cast<void *>( pTmpStruct ); + gpreg += nUsedGPR; + fpreg += nUsedSSE; + } + else + pCppArgs[nPos] = pCppStack = *ovrflw++; + } + else 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; + + 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 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; + code = codeSnippet( code, nFunctionOffset++, nVtableOffset, + x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) ); + + if ( ! pAttrTD->bReadOnly ) + { + // set method + (s++)->fn = code; + 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; + 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 * ) +{ +} diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/except.cxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/except.cxx new file mode 100644 index 000000000000..59ac557924d4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/except.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> +#include <sys/param.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 hash_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 __FreeBSD_version < 602103 + : 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 __FreeBSD_version < 602103 /* #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 = 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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/makefile.mk b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/makefile.mk new file mode 100644 index 000000000000..34d3846f6274 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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)" == "GCCFREEBSDXgcc3" + +.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 + +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_freebsd_x86-64/share.hxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/share.hxx new file mode 100644 index 000000000000..6aa69f0470e4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.3 $ + * + * 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 ); +} diff --git a/bridges/source/cpp_uno/gcc3_freebsd_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/uno2cpp.cxx new file mode 100644 index 000000000000..232ca94d4bc9 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_freebsd_x86-64/uno2cpp.cxx @@ -0,0 +1,561 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <string.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 "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_TypeDescription * pReturnTypeDescr, 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_TypeDescription * pReturnTypeDescr, 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 ( 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, "%f, ", pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( 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; + + 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" + : + : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ), + "m" ( rax ), "m" ( rdx ), "m" ( xmm0 ) + : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11" + ); + + switch (pReturnTypeDescr->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 = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0) + { + if (nRetSize > 8) + static_cast<sal_uInt64 *>(pRegisterReturn)[1] = rdx; + static_cast<sal_uInt64 *>(pRegisterReturn)[0] = rax; + } + 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 ); + +//================================================================================================== + +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; + } + + // 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, bSimpleReturn, + pStackStart, ( pStack - pStackStart ), + pGPR, nGPR, + pFPR, nFPR ); + // NO exception occured... + *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; // 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: + { + // 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 ); + } + } +} + +} } } 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..8fd1a38e4f51 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s @@ -0,0 +1,22 @@ +@ ARM support code for OpenOffice C++/UNO bridging +@ +@ Written by Peter Naulls <peter@chocky.org> +@ Modified by Caolan McNamara <caolanm@redhat.com> + .file "armhelper.s" + .text + .align 4 + .global privateSnippetExecutor + .type privateSnippetExecutor, %function +privateSnippetExecutor: + stmfd sp!, {r0-r3} @ follow other parameters on stack + mov r0, ip @ r0 points to functionoffset/vtable + mov ip, sp @ fix up the ip + stmfd sp!, {fp,ip,lr,pc} @ 8 x 4 => stack remains 8 aligned + sub fp, ip, #4 @ set frame pointer + + add r1, sp, #16 @ r1 points to this and params + bl cpp_vtable_call(PLT) + + add sp, sp, #32 @ restore stack + ldr fp, [sp, #-32] @ restore frame pointer + ldr pc, [sp, #-24] @ return 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..23e33acafaa4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx @@ -0,0 +1,535 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 (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 )) + { +#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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; + cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, + &nRegReturn ); + 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 simple_ret_type ) + { + if (!simple_ret_type) + functionIndex |= 0x80000000; + + unsigned long * p = (unsigned long *)code; + + *p++ = 0xE1A0C00F; + *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: + // 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; + + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >(member); + + bool issimple = bridges::cpp_uno::shared::isSimpleType( + pMethodTD->pReturnTypeRef); + + code = codeSnippet(code, functionOffset++, vtableOffset, + issimple); + 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); +} + +/* vi:set tabstop=4 shiftwidth=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..30173ed8cd18 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx @@ -0,0 +1,344 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vi:set tabstop=4 shiftwidth=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..6ebd13698b37 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# 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 + +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..a930897232df --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 ); +} +#endif +/* vi:set tabstop=4 shiftwidth=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..f59a16b2ac38 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx @@ -0,0 +1,633 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.4 $ + * + * 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 +{ + enum armlimits { MAX_GPR_REGS = 4 }; +} + +void MapReturn(long r0, long r1, typelib_TypeClass eReturnType, void *pRegisterReturn) +{ +#if !defined(__ARM_EABI__) && !defined(__SOFTFP__) + register float fret asm("f0"); + register double dret asm("f0"); +#endif + + switch( eReturnType ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = r1; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = 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: +#if defined(__ARM_EABI__) || defined(__SOFTFP__) + ((long*)pRegisterReturn)[0] = r0; +#else + *(float*)pRegisterReturn = fret; +#endif + break; + case typelib_TypeClass_DOUBLE: +#if defined(__ARM_EABI__) || defined(__SOFTFP__) + ((long*)pRegisterReturn)[1] = r1; + ((long*)pRegisterReturn)[0] = r0; +#else + *(double*)pRegisterReturn = dret; +#endif + break; + default: + break; + } +} + +namespace +{ +//================================================================ + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_uInt32 *pStack, + sal_uInt32 nStack, + sal_uInt32 *pGPR, + sal_uInt32 nGPR) __attribute__((noinline)); + +void callVirtualMethod( + void * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + 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; + + // fill registers + __asm__ __volatile__ ( + "ldr r0, [%0, #0]\n\t" + "ldr r1, [%0, #4]\n\t" + "ldr r2, [%0, #8]\n\t" + "ldr r3, [%0, #12]\n\t" + : : "r" (pGPR) + : "r0", "r1", "r2", "r3" + ); + + // tell gcc that r0 to r3 are not available to it + register sal_uInt32 r0 asm("r0"); + register sal_uInt32 r1 asm("r1"); + register sal_uInt32 r2 asm("r2"); + register sal_uInt32 r3 asm("r3"); + + (*pFunc)(r0, r1, r2, r3); + + // get return value + __asm__ __volatile__ ( + "mov %0, r0\n\t" + "mov %1, r1\n\t" + : "=r" (r0), "=r" (r1) : ); + + MapReturn(r0, r1, eReturnType, 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; + + 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, 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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; + } + // 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, pReturnTypeDescr->eTypeClass, + pStackStart, + (pStack - pStackStart), + pGPR, nGPR); + + // NO exception occured... + *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); + 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 ); + } + } +} + +} } } + +/* vi:set tabstop=4 shiftwidth=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..cd30e224bef5 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/call.cxx @@ -0,0 +1,145 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.2 $ + * + * 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); + +#ifdef CMC_DEBUG + 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); +} + +/* vi:set tabstop=4 shiftwidth=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..a78d7694c798 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx @@ -0,0 +1,728 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.2 $ + * + * 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 <hash_map> + +#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; + int nregs = 0; //number of words passed in registers + +#ifdef CMC_DEBUG + 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)) + { +#ifdef CMC_DEBUG + fprintf(stderr, "simple return\n"); +#endif + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else + { +#ifdef CMC_DEBUG + 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) & 4) + 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) & 4) + 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; + +#ifdef CMC_DEBUG + fprintf(stderr, "before dispatch\n"); +#endif + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + +#ifdef CMC_DEBUG + fprintf(stderr, "after dispatch\n"); +#endif + + // in case an exception occured... + 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 occured... + { + // 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); +#ifdef CMC_DEBUG + 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]; +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#ifdef CMC_DEBUG + 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::createFromAscii("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::createFromAscii("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; + + +#ifdef CMC_DEBUG + 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"); + } +} + +/* vi:set tabstop=4 shiftwidth=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..8242bacaedc6 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/except.cxx @@ -0,0 +1,337 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.2 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vi:set tabstop=4 shiftwidth=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..fcdcea72454f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/makefile.mk @@ -0,0 +1,86 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# 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 + +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..eedfdf75da8d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/share.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.2 $ + * + * 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 ); +} 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..a342568d5bf8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx @@ -0,0 +1,524 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.2 $ + * + * 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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 occured... + *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 ); + } + } +} + +} } } + +/* vi:set tabstop=4 shiftwidth=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..900560794513 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx @@ -0,0 +1,687 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.3 $ + * + * 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 */ ) +{ +#ifdef CMC_DEBUG + 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 ); + +#ifdef CMC_DEBUG + 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 )) + { +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + 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 ); + } + } + } + +#ifdef CMC_DEBUG + 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 occured... + 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 occured... + { + // 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]; +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is gpreg[0]\n"); +#endif + } + +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is %p\n", pThis); +#endif + + pThis = static_cast< char * >(pThis) - nVtableOffset; + +#ifdef CMC_DEBUG + 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(); + +#ifdef CMC_DEBUG + 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::createFromAscii("illegal vtable index!"), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + +#ifdef CMC_DEBUG + 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: + { +#ifdef CMC_DEBUG + fprintf(stderr, "screwed\n"); +#endif + + throw RuntimeException( + rtl::OUString::createFromAscii("no member description found!"), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + +#ifdef CMC_DEBUG + 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; + +#ifdef CMC_DEBUG + 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 ) +{ +#ifdef CMC_DEBUG + 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; +#ifdef CMC_DEBUG + 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; +} + +/* vi:set tabstop=4 shiftwidth=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..3bbf940ec55f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/except.cxx @@ -0,0 +1,290 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <hash_map> + +#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 hash_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 ); +} + +} +/* vi:set tabstop=4 shiftwidth=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..b8d9da98ff74 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.3 $ +# +# 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 + +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..4cd0c659b629 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/share.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.3 $ + * + * 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; + }; + } + } +} +/* vi:set tabstop=4 shiftwidth=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..d1d98f222738 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_ia64/uno2cpp.cxx @@ -0,0 +1,693 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.3 $ + * + * 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; + +#ifdef CMC_DEBUG + // 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) + { +#ifdef CMC_DEBUG + 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 +#ifdef CMC_DEBUG + fprintf(stderr, "simple return\n"); +#endif + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn); +#ifdef CMC_DEBUG + 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; + +#ifdef CMC_DEBUG + 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; + +#ifdef CMC_DEBUG + 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 ); + +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + fprintf(stderr, "byte is %x\n", *(unsigned char*)(pCppArgs[nPos])); +#endif + INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow ); + break; + case typelib_TypeClass_FLOAT: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + fprintf(stderr, "complex type again %d\n", rParam.bIn); +#endif + if (! rParam.bIn) // is pure out + { +#ifdef CMC_DEBUG + 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 )) + { +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + 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 occured... + *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 ); + } + } +} + +} } } +/* vi:set tabstop=4 shiftwidth=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..f345e3a764ac --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/call.s @@ -0,0 +1,268 @@ + .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 $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: + .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: + 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 + 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 $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: + .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 + 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 $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: + .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..6e6c2009dde8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx @@ -0,0 +1,492 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.14 $ + * + * 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 (bridges::cpp_uno::shared::isSimpleType( 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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_PtrDiff writetoexecdiff, sal_Int32 functionIndex, sal_Int32 vtableOffset, + typelib_TypeClass returnTypeClass) +{ + if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass)) { + 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_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_INTERFACE: + 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) - 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->eTypeClass); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + typelib_TypeClass_VOID); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, writetoexecdiff, functionOffset++, vtableOffset, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef->eTypeClass); + 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 *) +{} 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..a804fd17addc --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/except.cxx @@ -0,0 +1,333 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.14.20.1 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..1bf0819311fb --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.11 $ +# +# 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" + +.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 + +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 +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(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..7529230fde94 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 ); +} 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..2a88705ce01c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx @@ -0,0 +1,447 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.11 $ + * + * 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 "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_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 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; + 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; + + // 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 + 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->eTypeClass, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occured... + *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 ); + } + } +} + +} } } 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..1d63ebde491f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx @@ -0,0 +1,539 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.2 $ + * + * 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 <hash_map> + +#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; +#ifdef CMC_DEBUG + 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 )) + { +#ifdef CMC_DEBUG + fprintf(stderr, "simple return\n"); +#endif + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { +#ifdef CMC_DEBUG + 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; + +#ifdef CMC_DEBUG + fprintf(stderr, "before dispatch\n"); +#endif + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + +#ifdef CMC_DEBUG + fprintf(stderr, "after dispatch\n"); +#endif + + // in case an exception occured... + 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 occured... + { + // 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); +#ifdef CMC_DEBUG + 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::createFromAscii("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::createFromAscii("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); + + bool issimple = bridges::cpp_uno::shared::isSimpleType( + pMethodTD->pReturnTypeRef); + + 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*/) +{ +} + +/* vi:set tabstop=4 shiftwidth=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..8242bacaedc6 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/except.cxx @@ -0,0 +1,337 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.2 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, getAdjustedPtr(header), pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } + } +} + +/* vi:set tabstop=4 shiftwidth=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..8371d653a25b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# 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 + +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..10380f29e324 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/share.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.2 $ + * + * 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 ); +} 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..067279965923 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_m68k/uno2cpp.cxx @@ -0,0 +1,496 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.2 $ + * + * 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 ); + } + +#ifdef CMC_DEBUG + // 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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 occured... + *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 ); + } + } +} + +} } } + +/* vi:set tabstop=4 shiftwidth=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..ec4055ca74c4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx @@ -0,0 +1,806 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.6 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; +} + 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..88dd91e4e47a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/except.cxx @@ -0,0 +1,328 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..73bc2768869b --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/makefile.mk @@ -0,0 +1,85 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.3 $ +# +# 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 + +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..64224956fa40 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/share.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.3 $ + * + * 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 ); +} 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..19026bbdd01c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_mips/uno2cpp.cxx @@ -0,0 +1,600 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.4 $ + * + * 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 occured... + *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 ); + } + } +} +}}} + 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..e901a110213f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx @@ -0,0 +1,798 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.12 $ + * + * 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" +// #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 */ ) +{ + 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; +} + 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..adb10dae24c7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/except.cxx @@ -0,0 +1,290 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.9 $ + * + * 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 <hash_map> + +#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 hash_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 ); +} + +} + 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..d6cc303b88bd --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.10 $ +# +# 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 + +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..3b1956075514 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/share.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.6 $ + * + * 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 ); +} 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..8c527df2d48c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/uno2cpp.cxx @@ -0,0 +1,675 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.9 $ + * + * 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 occured... + *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 ); + } + } +} + +} } } 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..e514914db3b7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx @@ -0,0 +1,725 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 */ ) +{ +#ifdef CMC_DEBUG + 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 ); + +#ifdef CMC_DEBUG + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + 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 ); + } + } + } + +#ifdef CMC_DEBUG + 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 occured... + 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 occured... + { + // 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]; +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is gpreg[1]\n"); +#endif + } + else + { + pThis = gpreg[0]; +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is gpreg[0]\n"); +#endif + } + +#ifdef CMC_DEBUG + fprintf(stderr, "pThis is %lx\n", pThis); +#endif + + pThis = static_cast< char * >(pThis) - nVtableOffset; + +#ifdef CMC_DEBUG + 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(); + +#ifdef CMC_DEBUG + 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::createFromAscii("illegal vtable index!"), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + +#ifdef CMC_DEBUG + 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: + { +#ifdef CMC_DEBUG + fprintf(stderr, "screwed\n"); +#endif + + throw RuntimeException( + rtl::OUString::createFromAscii("no member description found!"), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + +#ifdef CMC_DEBUG + 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[0]; + + 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) +{ +#ifdef CMC_DEBUG + 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; +#ifdef CMC_DEBUG + 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; +#ifdef CMC_DEBUG + 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; +} + +/* vi:set tabstop=4 shiftwidth=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..9badda7c137a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/except.cxx @@ -0,0 +1,290 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 hash_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 ); +} + +} + 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..405e8bc6d2dc --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.3 $ +# +# 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 + +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..fdbc7a8f6b1c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 }; +} 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..628c26f4cea4 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx @@ -0,0 +1,603 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.4 $ + * + * 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; + +#ifdef CMC_DEBUG + // 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) + { +#ifdef CMC_DEBUG + fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass); +#endif + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types +#ifdef CMC_DEBUG + fprintf(stderr, "simple return\n"); +#endif + } + else + { + // complex return via ptr + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn); +#ifdef CMC_DEBUG + 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; +#ifdef CMC_DEBUG + 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; + +#ifdef CMC_DEBUG + 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 ); + +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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: +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + fprintf(stderr, "complex type again %d\n", rParam.bIn); +#endif + if (! rParam.bIn) // is pure out + { +#ifdef CMC_DEBUG + 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 )) + { +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + 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 occured... + *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 ); + } + } +} + +} } } 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..3ebc8a589df0 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx @@ -0,0 +1,698 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.6 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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) +{ +#ifdef CMC_DEBUG + 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; +#ifdef CMC_DEBUG + 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; +} + +/* vi:set tabstop=4 shiftwidth=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..0d49d0b95a74 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/except.cxx @@ -0,0 +1,290 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.7 $ + * + * 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 <hash_map> + +#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 hash_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 ) +{ + 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 ); +} + +} +/* vi:set tabstop=4 shiftwidth=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..9b27f0f5ad97 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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 + +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..ab8565341ece --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/share.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); +} +/* vi:set tabstop=4 shiftwidth=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..364464a28565 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390/uno2cpp.cxx @@ -0,0 +1,638 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.6 $ + * + * 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 occured... + *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 ) +{ +#ifdef CMC_DEBUG + fprintf(stderr, "unoInterfaceProxyDispatch\n"); +#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 ); + } + } +} + +} } } +/* vi:set tabstop=4 shiftwidth=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..e866e05f32c5 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx @@ -0,0 +1,655 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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 */ ) +{ +#ifdef CMC_DEBUG + 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 ); + +#ifdef CMC_DEBUG + fprintf(stderr, "arg %d of %d\n", nPos, nParams); +#endif + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { +#ifdef CMC_DEBUG + 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 + { +#ifdef CMC_DEBUG + 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 ); + } + } + } + +#ifdef CMC_DEBUG + 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 occured... + 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 occured... + { + // 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); + +#ifdef CMC_DEBUG + fprintf(stderr, "nVTableOffset, nFunctionIndex are %x %x\n", nVtableOffset, nFunctionIndex); +#endif + +#ifdef CMC_DEBUG + // 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::createFromAscii("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::createFromAscii("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_uInt32 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]; +#ifdef CMC_DEBUG + 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 ); +#ifdef CMC_DEBUG + fprintf(stderr, "after mediate ret is %lx %ld\n", nRegReturn[0], nRegReturn[0]); +#endif + + switch( aType ) + { + case typelib_TypeClass_VOID: + 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: + 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; +#ifdef CMC_DEBUG + 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; +} + +/* vi:set tabstop=4 shiftwidth=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..e474dce7268c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/except.cxx @@ -0,0 +1,291 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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 <hash_map> + +#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 hash_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 ) +{ + 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 ); +} + +} +/* vi:set tabstop=4 shiftwidth=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..b85bcb187d83 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.3 $ +# +# 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 + +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..8e56e324e315 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/share.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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 }; +} + +/* vi:set tabstop=4 shiftwidth=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..5940f566f9ca --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_s390x/uno2cpp.cxx @@ -0,0 +1,541 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * + * $Revision: 1.3 $ + * + * 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) +{ +#ifdef CMC_DEBUG + fprintf(stderr,"Mapping Return with %lx %ld %f\n", r2, r2, f0); +#endif + switch (eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *pRegisterReturn = r2; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *pRegisterReturn = (unsigned short)r2; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *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; + } +#ifdef CMC_DEBUG + fprintf(stderr, "end of MapReturn with %x\n", pRegisterReturn ? *pRegisterReturn : 0); +#endif +} + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ + { \ + float tmp = *reinterpret_cast<float *>( pSV ); \ + 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; + +#ifdef CMC_DEBUG + // 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 occured... + *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 ) +{ +#ifdef CMC_DEBUG + fprintf(stderr, "unoInterfaceProxyDispatch\n"); +#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 ); + } + } +} + +} } } +/* vi:set tabstop=4 shiftwidth=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..4e07c2c879d7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx @@ -0,0 +1,578 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.14 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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); + } +} 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..1024b7009478 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/except.cxx @@ -0,0 +1,331 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.8 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..2bf38b311f1d --- /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 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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 + +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..4316ec314ad7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/share.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.5 $ + * + * 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; +} + +} 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..8384bdc9a76e --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc/uno2cpp.cxx @@ -0,0 +1,603 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.11 $ + * + * 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 +{ +//================================================================================================== +// 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 occured... + *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 ); + } + } +} + +} } } 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..ad0faa1a01aa --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx @@ -0,0 +1,806 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: abi.cxx,v $ + * $Revision: 1.5 $ + * + * 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; + +typedef struct +{ + /* Registers for argument passing. */ + long gpr[MAX_GPR_REGS]; + __int128_t sse[MAX_SSE_REGS]; + + /* Stack space for arguments. */ + char argspace[0]; +} stackLayout; + +/* 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 + +#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) + +/* 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 &rByteOffset ) +{ + /* First, align to the right place. */ + rByteOffset = ALIGN( rByteOffset, pTypeRef->pType->nAlignment ); + + 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 ( ( rByteOffset % 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 ( ( rByteOffset % 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 ]; + rByteOffset = pStruct->pMemberOffsets[ nMember ]; + + int num = classify_argument( pTypeInStruct, subclasses, rByteOffset ); + + if ( num == 0 ) + { + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return 0; + } + + for ( int i = 0; i < num; i++ ) + { + int pos = rByteOffset / 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 offset = 0; + int n; + + n = classify_argument( pTypeRef, classes, offset ); + + 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 offset = 0; + int n; + + n = classify_argument( pTypeRef, classes, offset ); + + 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; + } +} + +#if 0 + +/* Functions to load floats and double to an SSE register placeholder. */ +extern void float2sse (float, __int128_t *); +extern void double2sse (double, __int128_t *); +extern void floatfloat2sse (void *, __int128_t *); + +/* Functions to put the floats and doubles back. */ +extern float sse2float (__int128_t *); +extern double sse2double (__int128_t *); +extern void sse2floatfloat(__int128_t *, void *); + +/*@-exportheader@*/ +void +ffi_prep_args (stackLayout *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ + int gprcount, ssecount, i, g, s; + void **p_argv; + void *argp = &stack->argspace; + ffi_type **p_arg; + + /* First check if the return value should be passed in memory. If so, + pass the pointer as the first argument. */ + gprcount = ssecount = 0; + if (ecif->cif->rtype->type != FFI_TYPE_VOID + && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0) + (void *)stack->gpr[gprcount++] = ecif->rvalue; + + for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue; + i!=0; i--, p_arg++, p_argv++) + { + int in_register = 0; + + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_UINT32: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + if (gprcount < MAX_GPR_REGS) + { + stack->gpr[gprcount] = 0; + stack->gpr[gprcount++] = *(long long *)(*p_argv); + in_register = 1; + } + break; + + case FFI_TYPE_FLOAT: + if (ssecount < MAX_SSE_REGS) + { + float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]); + in_register = 1; + } + break; + + case FFI_TYPE_DOUBLE: + if (ssecount < MAX_SSE_REGS) + { + double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]); + in_register = 1; + } + break; + } + + if (in_register) + continue; + + /* Either all places in registers where filled, or this is a + type that potentially goes into a memory slot. */ + if (examine_argument (*p_arg, 0, &g, &s) == 0 + || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) + { + /* Pass this argument in memory. */ + argp = (void *)ALIGN(argp, (*p_arg)->alignment); + memcpy (argp, *p_argv, (*p_arg)->size); + argp += (*p_arg)->size; + } + else + { + /* All easy cases are eliminated. Now fire the big guns. */ + + enum x86_64_reg_class classes[MAX_CLASSES]; + int offset = 0, j, num; + void *a; + + num = classify_argument (*p_arg, classes, &offset); + for (j=0, a=*p_argv; j<num; j++, a+=8) + { + switch (classes[j]) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + stack->gpr[gprcount++] = *(long long *)a; + break; + case X86_64_SSE_CLASS: + floatfloat2sse (a, &stack->sse[ssecount++]); + break; + case X86_64_SSESF_CLASS: + float2sse (*(float *)a, &stack->sse[ssecount++]); + break; + case X86_64_SSEDF_CLASS: + double2sse (*(double *)a, &stack->sse[ssecount++]); + break; + default: + abort(); + } + } + } + } +} + +/* Perform machine dependent cif processing. */ +ffi_status +ffi_prep_cif_machdep (ffi_cif *cif) +{ + int gprcount, ssecount, i, g, s; + + gprcount = ssecount = 0; + + /* Reset the byte count. We handle this size estimation here. */ + cif->bytes = 0; + + /* If the return value should be passed in memory, pass the pointer + as the first argument. The actual memory isn't allocated here. */ + if (cif->rtype->type != FFI_TYPE_VOID + && examine_argument (cif->rtype, 1, &g, &s) == 0) + gprcount = 1; + + /* Go over all arguments and determine the way they should be passed. + If it's in a register and there is space for it, let that be so. If + not, add it's size to the stack byte count. */ + for (i=0; i<cif->nargs; i++) + { + if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0 + || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) + { + /* This is passed in memory. First align to the basic type. */ + cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment); + + /* Stack arguments are *always* at least 8 byte aligned. */ + cif->bytes = ALIGN(cif->bytes, 8); + + /* Now add the size of this argument. */ + cif->bytes += cif->arg_types[i]->size; + } + else + { + gprcount += g; + ssecount += s; + } + } + + /* Set the flag for the closures return. */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + case FFI_TYPE_SINT64: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + cif->flags = (unsigned) cif->rtype->type; + break; + + case FFI_TYPE_UINT64: + cif->flags = FFI_TYPE_SINT64; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +typedef struct +{ + long gpr[2]; + __int128_t sse[2]; + long double st0; +} return_value; + +//#endif + +void +ffi_fill_return_value (return_value *rv, extended_cif *ecif) +{ + enum x86_64_reg_class classes[MAX_CLASSES]; + int i = 0, num; + long *gpr = rv->gpr; + __int128_t *sse = rv->sse; + signed char sc; + signed short ss; + + /* This is needed because of the way x86-64 handles signed short + integers. */ + switch (ecif->cif->rtype->type) + { + case FFI_TYPE_SINT8: + sc = *(signed char *)gpr; + *(long long *)ecif->rvalue = (long long)sc; + return; + case FFI_TYPE_SINT16: + ss = *(signed short *)gpr; + *(long long *)ecif->rvalue = (long long)ss; + return; + default: + /* Just continue. */ + ; + } + + num = classify_argument (ecif->cif->rtype, classes, &i); + + if (num == 0) + /* Return in memory. */ + ecif->rvalue = (void *) rv->gpr[0]; + else if (num == 2 && classes[0] == X86_64_X87_CLASS && + classes[1] == X86_64_X87UP_CLASS) + /* This is a long double (this is easiest to handle this way instead + of an eightbyte at a time as in the loop below. */ + *((long double *)ecif->rvalue) = rv->st0; + else + { + void *a; + + for (i=0, a=ecif->rvalue; i<num; i++, a+=8) + { + switch (classes[i]) + { + case X86_64_INTEGER_CLASS: + case X86_64_INTEGERSI_CLASS: + *(long long *)a = *gpr; + gpr++; + break; + case X86_64_SSE_CLASS: + sse2floatfloat (sse++, a); + break; + case X86_64_SSESF_CLASS: + *(float *)a = sse2float (sse++); + break; + case X86_64_SSEDF_CLASS: + *(double *)a = sse2double (sse++); + break; + default: + abort(); + } + } + } +} + +//#if 0 + +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *), + void (*) (return_value *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, /*@out@*/ unsigned *, void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ + +void ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue) +{ + extended_cif ecif; + int dummy; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + /* Stack must always be 16byte aligned. Make it so. */ + cif->bytes = ALIGN(cif->bytes, 16); + + switch (cif->abi) + { + case FFI_SYSV: + /* Calling 32bit code from 64bit is not possible */ + FFI_ASSERT(0); + break; + + case FFI_UNIX64: + /*@-usedef@*/ + ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif, + cif->bytes, ecif.rvalue, fn); + /*@=usedef@*/ + break; + + default: + FFI_ASSERT(0); + break; + } +} + +extern void ffi_closure_UNIX64(void); + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data) +{ + volatile unsigned short *tramp; + + /* FFI_ASSERT (cif->abi == FFI_OSF); */ + + tramp = (volatile unsigned short *) &closure->tramp[0]; + tramp[0] = 0xbb49; /* mov <code>, %r11 */ + tramp[5] = 0xba49; /* mov <data>, %r10 */ + tramp[10] = 0xff49; /* jmp *%r11 */ + tramp[11] = 0x00e3; + *(void * volatile *) &tramp[1] = ffi_closure_UNIX64; + *(void * volatile *) &tramp[6] = closure; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + return FFI_OK; +} + +int +ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp) +{ + ffi_cif *cif; + void **avalue; + ffi_type **arg_types; + long i, avn, argn; + + cif = closure->cif; + avalue = alloca(cif->nargs * sizeof(void *)); + + argn = 0; + + i = 0; + avn = cif->nargs; + arg_types = cif->arg_types; + + /* Grab the addresses of the arguments from the stack frame. */ + while (i < avn) + { + switch (arg_types[i]->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + { + if (l->gp_offset > 48-8) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->gp_offset; + l->gp_offset += 8; + } + } + break; + + case FFI_TYPE_STRUCT: + /* FIXME */ + FFI_ASSERT(0); + break; + + case FFI_TYPE_DOUBLE: + { + if (l->fp_offset > 176-16) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->fp_offset; + l->fp_offset += 16; + } + } +#if DEBUG_FFI + fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]); +#endif + break; + + case FFI_TYPE_FLOAT: + { + if (l->fp_offset > 176-16) + { + avalue[i] = l->overflow_arg_area; + l->overflow_arg_area = (char *)l->overflow_arg_area + 8; + } + else + { + avalue[i] = (char *)l->reg_save_area + l->fp_offset; + l->fp_offset += 16; + } + } +#if DEBUG_FFI + fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]); +#endif + break; + + default: + FFI_ASSERT(0); + } + + argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG; + i++; + } + + /* Invoke the closure. */ + (closure->fun) (cif, rp, avalue, closure->user_data); + + /* FIXME: Structs not supported. */ + FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT); + + /* Tell ffi_closure_UNIX64 how to perform return type promotions. */ + + return cif->rtype->type; +} + +#endif 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..c5b7d94d2e01 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/abi.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: abi.hxx,v $ + * $Revision: 1.3 $ + * + * 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_ 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..fc5a9af1ac5c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx @@ -0,0 +1,523 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.9 $ + * + * 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 <hash_map> + +#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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; + + 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 * ) +{ +} 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..e4862e8bc83a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/except.cxx @@ -0,0 +1,333 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.8 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..9b16f4ab5944 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.9 $ +# +# 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" + +.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 + +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..1a171ffe08a2 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); +} 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..23c40121afb7 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx @@ -0,0 +1,574 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.10 $ + * + * 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 <string.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 "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 ); + +//================================================================================================== + +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 + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeRef, bSimpleReturn, + pStackStart, ( pStack - pStackStart ), + pGPR, nGPR, + pFPR, nFPR ); + // NO exception occured... + *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 ); + } + } +} + +} } } 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..fc8860ab4ce1 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/call.s @@ -0,0 +1,331 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: call.s,v $ + * + * $Revision: 1.5 $ + * + * 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..8eaff1ad49ef --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/cpp2uno.cxx @@ -0,0 +1,522 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.7 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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); + 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 *) +{} 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..c2147dfed527 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/except.cxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..41f79c3d1f8f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# 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 +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(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..cbd6e2afa40d --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/share.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 ); +} 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..3fd38cc9af41 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_intel/uno2cpp.cxx @@ -0,0 +1,498 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.6 $ + * + * 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 <malloc.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 occured... + *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 ); + } + } +} + +} } } 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..fa5aa958f979 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx @@ -0,0 +1,733 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.11 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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; +} + 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..c7584ef5f20e --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/except.cxx @@ -0,0 +1,289 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.7 $ + * + * 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 <hash_map> + +#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 hash_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 ); +} + +} + 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..93e62299d3ce --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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..6f86271076a6 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/share.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.5 $ + * + * 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 ); +} 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..e3f4d36e3962 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_powerpc/uno2cpp.cxx @@ -0,0 +1,637 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.9 $ + * + * 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 occured... + *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 ); + } + } +} + +} } } diff --git a/bridges/source/cpp_uno/gcc3_netbsd_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_netbsd_intel/cpp2uno.cxx new file mode 100644 index 000000000000..a103da1e0d48 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_netbsd_intel/cpp2uno.cxx @@ -0,0 +1,566 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#include <sal/alloca.h> +#include <rtl/alloc.h> +#include <osl/mutex.hxx> + +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include <bridges/cpp_uno/bridge.hxx> +#include <bridges/cpp_uno/type_misc.hxx> + +#include "share.hxx" + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +//================================================================================================== +static typelib_TypeClass cpp2uno_call( + cppu_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 (cppu_isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (cppu_relatesToInterface( 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 && cppu_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 (cppu_relatesToInterface( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + &pThis->pBridge->aCpp2Uno ); + 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->pUnoI->pDispatcher)( pThis->pUnoI, pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occured... + 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 ); + + raiseException( &aUnoExc, &pThis->pBridge->aUno2Cpp ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occured... + { + // 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->pBridge->aUno2Cpp ); + } + // 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->pBridge->aUno2Cpp ); + // 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 nVtableCall, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, [ret *], this, params + // _this_ ptr is patched cppu_XInterfaceProxy object + cppu_cppInterfaceProxy * pCppI = NULL; + if( nVtableCall & 0x80000000 ) + { + nVtableCall &= 0x7fffffff; + pCppI = (cppu_cppInterfaceProxy *)(XInterface *)*(pCallStack +2); + } + else + { + pCppI = (cppu_cppInterfaceProxy *)(XInterface *)*(pCallStack +1); + } + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->pTypeDescr; + + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + if (nVtableCall >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( + OUString::createFromAscii("illegal vtable index!"), + (XInterface *)pCppI ); + } + + // determine called method + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nVtableCall]; + 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] == nVtableCall) + { + // 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 (nVtableCall) + { + 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->pBridge->pCppEnv->getRegisteredInterface)( + pCppI->pBridge->pCppEnv, + (void **)&pInterface, pCppI->oid.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( + OUString::createFromAscii("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( int nTableEntry, void** pCallStack ) __attribute__((regparm(2))); + +void cpp_vtable_call( int nTableEntry, void** pCallStack ) +{ + volatile long nRegReturn[2]; + typelib_TypeClass aType = cpp_mediate( nTableEntry, 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; + } +} + + +//================================================================================================== +class MediateClassData +{ + typedef ::std::hash_map< OUString, void *, OUStringHash > t_classdata_map; + t_classdata_map m_map; + Mutex m_mutex; + +public: + void const * get_vtable( typelib_InterfaceTypeDescription * pTD ) SAL_THROW( () ); + + inline MediateClassData() SAL_THROW( () ) + {} + ~MediateClassData() SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +MediateClassData::~MediateClassData() SAL_THROW( () ) +{ + OSL_TRACE( "> calling ~MediateClassData(): freeing mediate vtables." ); + + for ( t_classdata_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos ) + { + ::rtl_freeMemory( iPos->second ); + } +} +//-------------------------------------------------------------------------------------------------- +static inline void codeSnippet( char * code, sal_uInt32 vtable_pos, bool simple_ret_type ) SAL_THROW( () ) +{ + if (! simple_ret_type) + vtable_pos |= 0x80000000; + OSL_ASSERT( sizeof (long) == 4 ); + // mov $nPos, %eax + *code++ = 0xb8; + *(long *)code = vtable_pos; + code += sizeof (long); + // mov %esp, %edx + *code++ = 0x89; + *code++ = 0xe2; + // jmp cpp_vtable_call + *code++ = 0xe9; + *(long *)code = ((char *)cpp_vtable_call) - code - sizeof (long); +} +//__________________________________________________________________________________________________ +void const * MediateClassData::get_vtable( typelib_InterfaceTypeDescription * pTD ) SAL_THROW( () ) +{ + void * buffer; + + // avoiding locked counts + OUString const & unoName = *(OUString const *)&((typelib_TypeDescription *)pTD)->pTypeName; + { + MutexGuard aGuard( m_mutex ); + t_classdata_map::const_iterator iFind( m_map.find( unoName ) ); + if (iFind == m_map.end()) + { + // create new vtable + sal_Int32 nSlots = pTD->nMapFunctionIndexToMemberIndex; + buffer = ::rtl_allocateMemory( ((2+ nSlots) * sizeof (void *)) + (nSlots *20) ); + + ::std::pair< t_classdata_map::iterator, bool > insertion( + m_map.insert( t_classdata_map::value_type( unoName, buffer ) ) ); + OSL_ENSURE( insertion.second, "### inserting new vtable buffer failed?!" ); + + void ** slots = (void **)buffer; + *slots++ = 0; + *slots++ = 0; // rtti + char * code = (char *)(slots + nSlots); + + sal_uInt32 vtable_pos = 0; + sal_Int32 nAllMembers = pTD->nAllMembers; + typelib_TypeDescriptionReference ** ppAllMembers = pTD->ppAllMembers; + for ( sal_Int32 nPos = 0; nPos < nAllMembers; ++nPos ) + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, ppAllMembers[ nPos ] ); + OSL_ASSERT( pTD ); + if (typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass) + { + bool simple_ret = cppu_isSimpleType( + ((typelib_InterfaceAttributeTypeDescription *)pTD)->pAttributeTypeRef->eTypeClass ); + // get method + *slots++ = code; + codeSnippet( code, vtable_pos++, simple_ret ); + code += 20; + if (! ((typelib_InterfaceAttributeTypeDescription *)pTD)->bReadOnly) + { + // set method + *slots++ = code; + codeSnippet( code, vtable_pos++, true ); + code += 20; + } + } + else + { + bool simple_ret = cppu_isSimpleType( + ((typelib_InterfaceMethodTypeDescription *)pTD)->pReturnTypeRef->eTypeClass ); + *slots++ = code; + codeSnippet( code, vtable_pos++, simple_ret ); + code += 20; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + OSL_ASSERT( vtable_pos == nSlots ); + } + else + { + buffer = iFind->second; + } + } + + return ((void **)buffer +2); +} + +//================================================================================================== +void SAL_CALL cppu_cppInterfaceProxy_patchVtable( + XInterface * pCppI, typelib_InterfaceTypeDescription * pTypeDescr ) throw () +{ + static MediateClassData * s_pMediateClassData = 0; + if (! s_pMediateClassData) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pMediateClassData) + { +#ifdef LEAK_STATIC_DATA + s_pMediateClassData = new MediateClassData(); +#else + static MediateClassData s_aMediateClassData; + s_pMediateClassData = &s_aMediateClassData; +#endif + } + } + *(void const **)pCppI = s_pMediateClassData->get_vtable( pTypeDescr ); +} + +} + +extern "C" +{ +//################################################################################################## +sal_Bool SAL_CALL component_canUnload( TimeValue * pTime ) + SAL_THROW_EXTERN_C() +{ + return CPPU_CURRENT_NAMESPACE::g_moduleCount.canUnload( + &CPPU_CURRENT_NAMESPACE::g_moduleCount, pTime ); +} +//################################################################################################## +void SAL_CALL uno_initEnvironment( uno_Environment * pCppEnv ) + SAL_THROW_EXTERN_C() +{ + CPPU_CURRENT_NAMESPACE::cppu_cppenv_initEnvironment( + pCppEnv ); +} +//################################################################################################## +void SAL_CALL uno_ext_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) + SAL_THROW_EXTERN_C() +{ + CPPU_CURRENT_NAMESPACE::cppu_ext_getMapping( + ppMapping, pFrom, pTo ); +} +} diff --git a/bridges/source/cpp_uno/gcc3_netbsd_intel/except.cxx b/bridges/source/cpp_uno/gcc3_netbsd_intel/except.cxx new file mode 100644 index 000000000000..e47d2b4b4d34 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_netbsd_intel/except.cxx @@ -0,0 +1,334 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <bridges/cpp_uno/bridge.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> + +#include "share.hxx" + +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT ((void *) -2) +#endif + +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 hash_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( RTLD_DEFAULT, 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 defined DEBUG + OString cstr( + OUStringToOString( + *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if defined DEBUG + OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> c++ exception occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + diff --git a/bridges/source/cpp_uno/gcc3_netbsd_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_netbsd_intel/makefile.mk new file mode 100644 index 000000000000..b510f5a132d8 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_netbsd_intel/makefile.mk @@ -0,0 +1,79 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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)" == "GCCNETBSDIgcc3" + +.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= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/cpp_uno/gcc3_netbsd_intel/share.hxx b/bridges/source/cpp_uno/gcc3_netbsd_intel/share.hxx new file mode 100644 index 000000000000..9f7c6b8fae9a --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_netbsd_intel/share.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 <typeinfo> +#include <exception> +#include <cstddef> + +namespace CPPU_CURRENT_NAMESPACE +{ + +// ----- 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 ); +} diff --git a/bridges/source/cpp_uno/gcc3_netbsd_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_netbsd_intel/uno2cpp.cxx new file mode 100644 index 000000000000..0d4343d20d43 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_netbsd_intel/uno2cpp.cxx @@ -0,0 +1,436 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.6 $ + * + * 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 <rtl/alloc.h> + +#include <uno/data.h> +#include <bridges/cpp_uno/bridge.hxx> +#include <bridges/cpp_uno/type_misc.hxx> + +#include "share.hxx" + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ); + +//================================================================================================== +// 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 * pThis, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ) __attribute__((noinline)); + +void callVirtualMethod( + void * pThis, + 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 && pThis, "### 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 (! pThis) 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"(pThis), "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( + cppu_unoInterfaceProxy * pThis, + sal_Int32 nVtableCall, + 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 (cppu_isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (cppu_relatesToInterface( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + // push this + *(void**)pCppStack = pThis->pCppI; + 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 && cppu_isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + &pThis->pBridge->aUno2Cpp ); + + 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 (cppu_relatesToInterface( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, &pThis->pBridge->aUno2Cpp ); + + 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( + pThis->pCppI, nVtableCall, + pCppReturn, pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + // NO exception occured... + *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->pBridge->aCpp2Uno ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + &pThis->pBridge->aCpp2Uno ); + } + // 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->pBridge->aCpp2Uno ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch (...) + { + // fill uno exception + fillUnoException( __cxa_get_globals()->caughtExceptions, *ppUnoExc, &pThis->pBridge->aCpp2Uno ); + + // 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 ); + } +} + + +//================================================================================================== +void SAL_CALL cppu_unoInterfaceProxy_dispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) throw () +{ + // is my surrogate + cppu_unoInterfaceProxy * pThis = (cppu_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!" ); + + sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos]; + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, nVtableCall, + ((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 + cpp_call( + pThis, nVtableCall +1, // 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!" ); + + sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos]; + OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + + switch (nVtableCall) + { + // 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->pUnoEnv->getRegisteredInterface)( + pThis->pBridge->pUnoEnv, + (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, nVtableCall, + ((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 ); + } + } +} + +} + diff --git a/bridges/source/cpp_uno/gcc3_os2_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_os2_intel/cpp2uno.cxx new file mode 100644 index 000000000000..d6589b8d86cf --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/cpp2uno.cxx @@ -0,0 +1,528 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <sal/alloca.h> +#include <stdio.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 = {0}; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); +#if OSL_DEBUG_LEVEL > 1 + if (pUnoExc != NULL) + fprintf( stderr, ">cpp2uno_call pUnoExc %x\n", pUnoExc); +#endif + + // in case an exception occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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 *) +{} diff --git a/bridges/source/cpp_uno/gcc3_os2_intel/defs/gcc3_uno.def b/bridges/source/cpp_uno/gcc3_os2_intel/defs/gcc3_uno.def new file mode 100644 index 000000000000..1d7ee1a7a571 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/defs/gcc3_uno.def @@ -0,0 +1,915 @@ +LIBRARY gcc3_uno INITINSTANCE TERMINSTANCE
+DATA MULTIPLE
+DESCRIPTION 'StarView 3.00 680 '
+EXPORTS
+_GetVersionInfo
+_component_canUnload
+_uno_initEnvironment
+_uno_ext_getMapping
+
+;lmax=20
+;smax=_component_canUnload
+
+;__ZTIN4test19TestBridgeExceptionE
+
+__ZTIN10comphelper18OPropertyContainerE
+__ZTIN10comphelper24OPropertyContainerHelperE
+__ZTIN10comphelper25OPropertyArrayUsageHelperIN9configmgr22OConfigurationProviderEEE
+__ZTIN3com3sun4star13configuration17XTemplateInstanceE
+__ZTIN3com3sun4star13configuration18XTemplateContainerE
+__ZTIN3com3sun4star13configuration29InvalidBootstrapFileExceptionE
+__ZTIN3com3sun4star13configuration29MissingBootstrapFileExceptionE
+__ZTIN3com3sun4star13configuration31InstallationIncompleteExceptionE
+__ZTIN3com3sun4star13configuration32CannotLoadConfigurationExceptionE
+__ZTIN3com3sun4star13configuration7backend13XLayerHandlerE
+__ZTIN3com3sun4star13configuration7backend14XSchemaHandlerE
+__ZTIN3com3sun4star13configuration7backend14XUpdateHandlerE
+__ZTIN3com3sun4star13configuration7backend15XCompositeLayerE
+__ZTIN3com3sun4star13configuration7backend15XSchemaSupplierE
+__ZTIN3com3sun4star13configuration7backend15XUpdatableLayerE
+__ZTIN3com3sun4star13configuration7backend16XBackendEntitiesE
+__ZTIN3com3sun4star13configuration7backend18XMultiLayerStratumE
+__ZTIN3com3sun4star13configuration7backend21BackendSetupExceptionE
+__ZTIN3com3sun4star13configuration7backend22BackendAccessExceptionE
+__ZTIN3com3sun4star13configuration7backend22CannotConnectExceptionE
+__ZTIN3com3sun4star13configuration7backend22MalformedDataExceptionE
+__ZTIN3com3sun4star13configuration7backend23ConnectionLostExceptionE
+__ZTIN3com3sun4star13configuration7backend23XBackendChangesListenerE
+__ZTIN3com3sun4star13configuration7backend23XBackendChangesNotifierE
+__ZTIN3com3sun4star13configuration7backend24StratumCreationExceptionE
+__ZTIN3com3sun4star13configuration7backend24XVersionedSchemaSupplierE
+__ZTIN3com3sun4star13configuration7backend29AuthenticationFailedExceptionE
+__ZTIN3com3sun4star13configuration7backend33InsufficientAccessRightsExceptionE
+__ZTIN3com3sun4star13configuration7backend39InvalidAuthenticationMechanismExceptionE
+__ZTIN3com3sun4star13configuration7backend6XLayerE
+__ZTIN3com3sun4star13configuration7backend7XSchemaE
+__ZTIN3com3sun4star13configuration7backend8XBackendE
+__ZTIN3com3sun4star2io11IOExceptionE
+__ZTIN3com3sun4star2io12XInputStreamE
+__ZTIN3com3sun4star2io13XOutputStreamE
+__ZTIN3com3sun4star2io15XActiveDataSinkE
+__ZTIN3com3sun4star2io16XDataInputStreamE
+__ZTIN3com3sun4star2io17XActiveDataSourceE
+__ZTIN3com3sun4star2io20WrongFormatExceptionE
+__ZTIN3com3sun4star2io21NotConnectedExceptionE
+__ZTIN3com3sun4star2io22UnexpectedEOFExceptionE
+__ZTIN3com3sun4star2io27BufferSizeExceededExceptionE
+__ZTIN3com3sun4star3uno10XInterfaceE
+__ZTIN3com3sun4star3uno15XCurrentContextE
+__ZTIN3com3sun4star3uno16RuntimeExceptionE
+__ZTIN3com3sun4star3uno17XComponentContextE
+__ZTIN3com3sun4star3uno5XWeakE
+__ZTIN3com3sun4star3uno9ExceptionE
+__ZTIN3com3sun4star3xml3sax12SAXExceptionE
+__ZTIN3com3sun4star3xml3sax14XAttributeListE
+__ZTIN3com3sun4star3xml3sax16XDocumentHandlerE
+;__ZTIN3com3sun4star4l
+__ZTIN3com3sun4star4lang10XComponentE
+__ZTIN3com3sun4star4lang10XUnoTunnelE
+__ZTIN3com3sun4star4lang12XLocalizableE
+__ZTIN3com3sun4star4lang12XServiceInfoE
+__ZTIN3com3sun4star4lang13XTypeProviderE
+__ZTIN3com3sun4star4lang14XEventListenerE
+__ZTIN3com3sun4star4lang15XInitializationE
+__ZTIN3com3sun4star4lang17DisposedExceptionE
+__ZTIN3com3sun4star4lang18NoSupportExceptionE
+__ZTIN3com3sun4star4lang20NullPointerExceptionE
+__ZTIN3com3sun4star4lang20XMultiServiceFactoryE
+__ZTIN3com3sun4star4lang21XSingleServiceFactoryE
+__ZTIN3com3sun4star4lang22IllegalAccessExceptionE
+__ZTIN3com3sun4star4lang22WrappedTargetExceptionE
+__ZTIN3com3sun4star4lang23XSingleComponentFactoryE
+__ZTIN3com3sun4star4lang24IllegalArgumentExceptionE
+__ZTIN3com3sun4star4lang29ServiceNotRegisteredExceptionE
+__ZTIN3com3sun4star4lang29WrappedTargetRuntimeExceptionE
+__ZTIN3com3sun4star4task17XInteractionAbortE
+__ZTIN3com3sun4star4task17XInteractionRetryE
+__ZTIN3com3sun4star4task19XInteractionApproveE
+__ZTIN3com3sun4star4task19XInteractionRequestE
+__ZTIN3com3sun4star4task22XInteractionDisapproveE
+__ZTIN3com3sun4star4task24XInteractionContinuationE
+__ZTIN3com3sun4star4util10XFlushableE
+__ZTIN3com3sun4star4util12XRefreshableE
+__ZTIN3com3sun4star4util12XTimeStampedE
+__ZTIN3com3sun4star4util13XChangesBatchE
+__ZTIN3com3sun4star4util13XStringEscapeE
+__ZTIN3com3sun4star4util16XChangesNotifierE
+__ZTIN3com3sun4star5beans10XExactNameE
+__ZTIN3com3sun4star5beans12XPropertySetE
+__ZTIN3com3sun4star5beans14XPropertyStateE
+__ZTIN3com3sun4star5beans16XFastPropertySetE
+__ZTIN3com3sun4star5beans16XPropertySetInfoE
+__ZTIN3com3sun4star5beans17XMultiPropertySetE
+__ZTIN3com3sun4star5beans18XPropertyWithStateE
+__ZTIN3com3sun4star5beans20XMultiPropertyStatesE
+__ZTIN3com3sun4star5beans21PropertyVetoExceptionE
+__ZTIN3com3sun4star5beans24UnknownPropertyExceptionE
+__ZTIN3com3sun4star5beans24XHierarchicalPropertySetE
+__ZTIN3com3sun4star5beans29XMultiHierarchicalPropertySetE
+__ZTIN3com3sun4star5beans9XPropertyE
+__ZTIN3com3sun4star6script22CannotConvertExceptionE
+__ZTIN3com3sun4star8registry12XRegistryKeyE
+__ZTIN3com3sun4star8registry15XSimpleRegistryE
+__ZTIN3com3sun4star8registry21InvalidValueExceptionE
+__ZTIN3com3sun4star8registry22MergeConflictExceptionE
+__ZTIN3com3sun4star8registry24InvalidRegistryExceptionE
+__ZTIN3com3sun4star9container10XContainerE
+__ZTIN3com3sun4star9container11XNameAccessE
+__ZTIN3com3sun4star9container12XNameReplaceE
+__ZTIN3com3sun4star9container14XElementAccessE
+__ZTIN3com3sun4star9container14XNameContainerE
+__ZTIN3com3sun4star9container17XHierarchicalNameE
+__ZTIN3com3sun4star9container21ElementExistExceptionE
+__ZTIN3com3sun4star9container22NoSuchElementExceptionE
+__ZTIN3com3sun4star9container23XHierarchicalNameAccessE
+__ZTIN3com3sun4star9container6XChildE
+__ZTIN3com3sun4star9container6XNamedE
+__ZTIN3vos10IReferenceE
+__ZTIN3vos10OReferenceE
+__ZTIN3vos6OTimerE
+__ZTIN3vos7OObjectE
+__ZTIN3vos7OThreadE
+__ZTIN3vos9IRunnableE
+__ZTIN4cppu11ImplHelper2IN3com3sun4star8registry15XSimpleRegistryENS3_4util10XFlushableEEE
+__ZTIN4cppu11ImplHelper4IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XLocalizableENS3_4util12XRefreshableENS7_10XFlushableEEE
+__ZTIN4cppu11ImplHelper6IN3com3sun4star5beans12XPropertySetENS4_17XMultiPropertySetENS4_24XHierarchicalPropertySetENS4_29XMultiHierarchicalPropertySetENS4_14XPropertyStateENS4_20XMultiPropertyStatesEEE
+__ZTIN4cppu11ImplHelper6IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyEEE
+__ZTIN4cppu11ImplHelper9IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyENS9_16XPropertySetInfoENS3_13configuration18XTemplateCo!_yPkJc2
+__ZTIN4cppu11OWeakObjectE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend13XLayerHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend14XSchemaHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend15XCompositeLayerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend23XBackendChangesListenerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io13XOutputStreamEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io16XDataInputStreamEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3uno15XCurrentContextEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax14XAttributeListEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax16XDocumentHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang14XEventListenerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang23XSingleComponentFactoryEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionAbortEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionRetryEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionApproveEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionRequestEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task22XInteractionDisapproveEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star5beans16XPropertySetInfoEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star8registry12XRegistryKeyEEE
+__ZTIN4cppu15WeakImplHelper2IN3com3sun4star13configuration7backend13XLayerHandlerENS5_6XLayerEEE
+__ZTIN4cppu15WeakImplHelper2IN3com3sun4star3uno15XCurrentContextENS3_4lang10XUnoTunnelEEE
+__ZTIN4cppu15WeakImplHelper3IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_13configuration7backend14XUpdateHandlerEEE
+__ZTIN4cppu15WeakImplHelper3IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang12XServiceInfoEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend6XLayerEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend7XSchemaEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io17XActiveDataSourceENS3_13configuration7backend13XLayerHandlerEEE
+__ZTIN4cppu15WeakImplHelper5IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableEEE
+__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang10XComponentENS7_12XServiceInfoENS3_13configuration17XTemplateInstanceENS7_10XUnoTunnelEEE
+__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableENS6_13XChangesBatchEEE
+__ZTIN4cppu18OPropertySetHelperE
+__ZTIN4cppu22ImplInheritanceHelper1IN9configmgr7localbe16LocalStratumBaseEN3com3sun4star13configuration7backend18XMultiLayerStratumEEE
+__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend6XLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu22ImplInheritanceHelper3IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS8_15XCompositeLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu24WeakComponentImplHelper1IN3com3sun4star4lang12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper2IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star13configuration7backend24XVersionedSchemaSupplierENS3_4lang15XInitializationENS7_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star3uno17XComponentContextENS4_15XCurrentContextENS3_4lang12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star4lang15XInitializationENS3_13configuration7backend16XBackendEntitiesENS4_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend15XSchemaSupplierENS5_18XMultiLayerStratumENS5_16XBackendEntitiesENS3_4lang15XInitializationENS9_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_15XSchemaSupplierENS3_4lang15XInitializationENS9_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper7IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_24XVersionedSchemaSupplierENS5_23XBackendChangesNotifierENS5_23XBackendChangesListenerENS3_4lang15XInitializationEN!_7c1rO0
+__ZTIN4cppu27WeakComponentImplHelperBaseE
+__ZTIN9configmgr10BasicGroupE
+__ZTIN9configmgr10IInterfaceE
+__ZTIN9configmgr10NodeActionE
+__ZTIN9configmgr10RefcountedE
+__ZTIN9configmgr10RemoveNodeE
+__ZTIN9configmgr10SearchNodeE
+__ZTIN9configmgr11NoncopyableE
+__ZTIN9configmgr11TreeManagerE
+__ZTIN9configmgr11TreeUpdaterE
+__ZTIN9configmgr11ValueChangeE
+__ZTIN9configmgr12CollectNamesE
+__ZTIN9configmgr12ITreeManagerE
+__ZTIN9configmgr12ONameCreatorE
+__ZTIN9configmgr12OPathCreatorINS_13configuration12AbsolutePathEEE
+__ZTIN9configmgr12OPathCreatorINS_13configuration12RelativePathEEE
+__ZTIN9configmgr13BasicValueSetE
+__ZTIN9configmgr13configuration100_GLOBAL__N__ZN9configmgr13configuration12TemplateName18makeSimpleTypeNameERKN3com3sun4star3uno4TypeE12TypeDetectorE
+__ZTIN9configmgr13configuration11InvalidNameE
+__ZTIN9configmgr13configuration11NodeVisitorE
+__ZTIN9configmgr13configuration11SetNodeImplE
+__ZTIN9configmgr13configuration12TypeMismatchE
+__ZTIN9configmgr13configuration13GroupNodeImplE
+__ZTIN9configmgr13configuration14SetNodeVisitorE
+__ZTIN9configmgr13configuration15ValueMemberNode12DeferredImplE
+__ZTIN9configmgr13configuration18GroupMemberVisitorE
+__ZTIN9configmgr13configuration19ConstraintViolationE
+__ZTIN9configmgr13configuration19DeferredSetNodeImplE
+__ZTIN9configmgr13configuration19WrappedUnoExceptionE
+__ZTIN9configmgr13configuration21DeferredGroupNodeImplE
+__ZTIN9configmgr13configuration21TemplateProvider_ImplE
+__ZTIN9configmgr13configuration28SpecialTemplateProvider_ImplE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv15CollectValueIDsE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv17SetVisitorAdapterE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv19GroupVisitorAdapterE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv21FindNonDefaultElementE
+__ZTIN9configmgr13configuration88_GLOBAL__N__ZN9configmgr13configuration17GroupUpdateHelperC2ERKNS0_4TreeERKNS0_7NodeRefE13NodeDefaulterE
+__ZTIN9configmgr13configuration8NodeImplE
+__ZTIN9configmgr13configuration8TemplateE
+__ZTIN9configmgr13configuration9ExceptionE
+__ZTIN9configmgr13INodeListenerE
+__ZTIN9configmgr13OInnerSetInfoE
+__ZTIN9configmgr13OMergeChangesE
+__ZTIN9configmgr13OProviderImplE
+__ZTIN9configmgr13PWMutexHolderE
+__ZTIN9configmgr13SubtreeChangeE
+__ZTIN9configmgr14BasicSetAccessE
+__ZTIN9configmgr14OStripDefaultsE
+__ZTIN9configmgr15BasicSetElementE
+__ZTIN9configmgr15IConfigListenerE
+__ZTIN9configmgr15OInnerGroupInfoE
+__ZTIN9configmgr15ProviderFactoryE
+__ZTIN9configmgr15ProviderWrapperE
+__ZTIN9configmgr16BasicGroupAccessE
+__ZTIN9configmgr16BasicPropertySetE
+__ZTIN9configmgr16BasicRootElementE
+__ZTIN9configmgr16BootstrapContextE
+__ZTIN9configmgr16ChangeTreeActionE
+__ZTIN9configmgr16ComponentContextE
+__ZTIN9configmgr16IDefaultProviderE
+__ZTIN9configmgr16ITemplateManagerE
+__ZTIN9configmgr16NodeModificationE
+__ZTIN9configmgr16OMergeRemoveNodeE
+__ZTIN9configmgr16OPropagateLevelsE
+__ZTIN9configmgr16UnoContextTunnel6TunnelE
+__ZTIN9configmgr17AttributeListImplE
+__ZTIN9configmgr17BasicInnerElementE
+__ZTIN9configmgr17CacheClientAccessE
+__ZTIN9configmgr17ExtendedCacheDataE
+__ZTIN9configmgr17OInnerGroupUpdateE
+__ZTIN9configmgr17OMergeValueChangeE
+__ZTIN9configmgr17TemplateCacheDataE
+__ZTIN9configmgr18BasicUpdateElementE
+__ZTIN9configmgr18CacheLoadingAccessE
+__ZTIN9configmgr18DisposingForwarderE
+__ZTIN9configmgr18IConfigBroadcasterE
+__ZTIN9configmgr18IConfigTreeManagerE
+__ZTIN9configmgr18OSetElementSetInfoE
+__ZTIN9configmgr19OInnerTreeSetUpdateE
+__ZTIN9configmgr19ORootElementSetInfoE
+__ZTIN9configmgr20OCacheWriteScheduler5TimerE
+__ZTIN9configmgr20OInnerValueSetUpdateE
+__ZTIN9configmgr20OMergeTreeChangeListE
+__ZTIN9configmgr20OSetElementGroupInfoE
+__ZTIN9configmgr20ServiceComponentImplE
+__ZTIN9configmgr21ORootElementGroupInfoE
+__ZTIN9configmgr21OTreeDisposeScheduler5TimerE
+__ZTIN9configmgr21SubtreeChangeReferrerE
+__ZTIN9configmgr22ChangeTreeModificationE
+__ZTIN9configmgr22IConfigDefaultProviderE
+__ZTIN9configmgr22IConfigTemplateManagerE
+__ZTIN9configmgr22OConfigurationProviderE
+__ZTIN9configmgr22OConfigurationRegistryE
+__ZTIN9configmgr22OSetElementGroupUpdateE
+__ZTIN9configmgr23ConfigChangeBroadcasterE
+__ZTIN9configmgr23IDefaultableTreeManagerE
+__ZTIN9configmgr23ORootElementGroupUpdateE
+__ZTIN9configmgr24OSetElementTreeSetUpdateE
+__ZTIN9configmgr25OConfigurationRegistryKeyE
+__ZTIN9configmgr25ORootElementTreeSetUpdateE
+__ZTIN9configmgr25OSetElementValueSetUpdateE
+__ZTIN9configmgr26OProviderDisposingListenerE
+__ZTIN9configmgr26ORootElementValueSetUpdateE
+__ZTIN9configmgr3xml11BasicParserE
+__ZTIN9configmgr3xml11LayerWriterE
+__ZTIN9configmgr3xml13ElementParser12BadValueTypeE
+__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend6XLayerEEE
+__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend7XSchemaEEE
+__ZTIN9configmgr3xml13WriterServiceIN3com3sun4star13configuration7backend13XLayerHandlerEEE
+__ZTIN9configmgr3xml18LayerParserServiceE
+__ZTIN9configmgr3xml19SchemaParserServiceE
+__ZTIN9configmgr4data10SetVisitorE
+__ZTIN9configmgr4data11NodeVisitorE
+__ZTIN9configmgr4data11TreeSegment4ImplE
+__ZTIN9configmgr4data15TreeNodeBuilder12LinkSetNodesE
+__ZTIN9configmgr4data20BasicDataTreeBuilderE
+__ZTIN9configmgr4data21ConvertingNodeBuilderE
+__ZTIN9configmgr4data21DataTreeDefaultMergerE
+__ZTIN9configmgr4data22CopyingDataTreeBuilder18ElementListBuilderE
+__ZTIN9configmgr4data22CopyingDataTreeBuilderE
+__ZTIN9configmgr4data24ConvertingSubnodeBuilderE
+__ZTIN9configmgr4data25ConvertingDataTreeBuilder18ElementListBuilderE
+__ZTIN9configmgr4data25ConvertingDataTreeBuilderE
+__ZTIN9configmgr4view12ViewStrategyE
+__ZTIN9configmgr4view18DirectViewStrategyE
+__ZTIN9configmgr4view20ReadOnlyViewStrategyE
+__ZTIN9configmgr5INodeE
+__ZTIN9configmgr6ChangeE
+__ZTIN9configmgr6memory11HeapManagerE
+__ZTIN9configmgr6memory14SimpleHeapLockE
+__ZTIN9configmgr6memory21SimpleHeapManagerBaseE
+__ZTIN9configmgr6memory25SimpleCheckingHeapManagerE
+__ZTIN9configmgr6memory8DataLockE
+__ZTIN9configmgr7AddNodeE
+__ZTIN9configmgr7backend10NodeUpdateE
+__ZTIN9configmgr7backend11NamedUpdateE
+__ZTIN9configmgr7backend11NodeReplaceE
+__ZTIN9configmgr7backend11PropertyAddE
+__ZTIN9configmgr7backend12ResultHolderINS0_12NodeInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend12ResultHolderINS0_16TemplateInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend12ResultHolderINS0_17ComponentInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend13BackendAccessE
+__ZTIN9configmgr7backend13ElementUpdateE
+__ZTIN9configmgr7backend13PropertyResetE
+__ZTIN9configmgr7backend13SchemaBuilderE
+__ZTIN9configmgr7backend13UpdateServiceE
+__ZTIN9configmgr7backend14PropertyUpdateE
+__ZTIN9configmgr7backend15CacheControllerE
+__ZTIN9configmgr7backend16NodeModificationE
+__ZTIN9configmgr7backend17BasicUpdateMergerE
+__ZTIN9configmgr7backend17BinaryReader_ImplE
+__ZTIN9configmgr7backend17INodeDataListenerE
+__ZTIN9configmgr7backend17INodeDataProviderE
+__ZTIN9configmgr7backend17LayerMergeHandlerE
+__ZTIN9configmgr7backend17LayerUpdateMergerE
+__ZTIN9configmgr7backend18BasicImportHandlerE
+__ZTIN9configmgr7backend18BinaryWriteHandlerE
+__ZTIN9configmgr7backend18ImportMergeHandlerE
+__ZTIN9configmgr7backend18LayerUpdateHandlerE
+__ZTIN9configmgr7backend19ICachedDataListenerE
+__ZTIN9configmgr7backend19ICachedDataNotifierE
+__ZTIN9configmgr7backend19ICachedDataProviderE
+__ZTIN9configmgr7backend19IDirectDataProviderE
+__ZTIN9configmgr7backend19IMergedDataProviderE
+__ZTIN9configmgr7backend19INodeUpdateProviderE
+__ZTIN9configmgr7backend19LayerDefaultRemoverE
+__ZTIN9configmgr7backend19MultiStratumBackendE
+__ZTIN9configmgr7backend20IDefaultDataProviderE
+__ZTIN9configmgr7backend20SingleBackendAdapterE
+__ZTIN9configmgr7backend21BackendChangeNotifierE
+__ZTIN9configmgr7backend21IDataProviderMetaDataE
+__ZTIN9configmgr7backend21ITemplateDataProviderE
+__ZTIN9configmgr7backend21OInvalidateTreeThreadE
+__ZTIN9configmgr7backend22CacheChangeMulticasterE
+__ZTIN9configmgr7backend22IComponentDataProviderE
+__ZTIN9configmgr7backend8NodeDropE
+__ZTIN9configmgr7localbe16LocalStratumBaseE
+__ZTIN9configmgr7localbe17LocalMultiStratumE
+__ZTIN9configmgr7localbe18FlatLocalFileLayerE
+__ZTIN9configmgr7localbe18LocalSingleBackendE
+__ZTIN9configmgr7localbe19BasicLocalFileLayerE
+__ZTIN9configmgr7localbe19LayerPropertyHelperE
+__ZTIN9configmgr7localbe19LocalSchemaSupplierE
+__ZTIN9configmgr7localbe20SimpleLocalFileLayerE
+__ZTIN9configmgr7localbe23CompositeLocalFileLayerE
+__ZTIN9configmgr7localbe23LocalStratumMutexHolderE
+__ZTIN9configmgr7localbe27FullCompositeLocalFileLayerE
+__ZTIN9configmgr7localbe28BasicCompositeLocalFileLayerE
+__ZTIN9configmgr7SubtreeE
+__ZTIN9configmgr8BasicSetE
+__ZTIN9configmgr8ISubtreeE
+__ZTIN9configmgr8OOptionsE
+__ZTIN9configmgr9apihelper15BroadcasterBaseE
+__ZTIN9configmgr9apihelper17PropertySetHelperE
+__ZTIN9configmgr9apihelper18InteractionRequestE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionAbortEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionRetryEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task19XInteractionApproveEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task22XInteractionDisapproveEEE
+__ZTIN9configmgr9apihelper24SimpleInteractionRequestE
+__ZTIN9configmgr9apihelper31ConfigurationInteractionHandler7ContextE
+__ZTIN9configmgr9CacheDataE
+__ZTIN9configmgr9configapi10NodeAccessE
+__ZTIN9configmgr9configapi10SetElementE
+__ZTIN9configmgr9configapi11ApiTreeImpl16ComponentAdapterE
+__ZTIN9configmgr9configapi11Broadcaster4ImplE
+__ZTIN9configmgr9configapi11NodeElementE
+__ZTIN9configmgr9configapi11OSetElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi11RootElementE
+__ZTIN9configmgr9configapi11TreeElementE
+__ZTIN9configmgr9configapi12InnerElementE
+__ZTIN9configmgr9configapi13NodeSetAccessE
+__ZTIN9configmgr9configapi13OInnerElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi14ObjectRegistryE
+__ZTIN9configmgr9configapi15ApiRootTreeImpl12NodeListenerE
+__ZTIN9configmgr9configapi15NodeGroupAccessE
+__ZTIN9configmgr9configapi16OReadRootElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi16OReadRootElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi17CollectPropertiesE
+__ZTIN9configmgr9configapi17NodeSetInfoAccessE
+__ZTIN9configmgr9configapi17NodeTreeSetAccessE
+__ZTIN9configmgr9configapi17UpdateRootElementE
+__ZTIN9configmgr9configapi18NodeValueSetAccessE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi19NodeGroupInfoAccessE
+__ZTIN9configmgr9configapi19NodePropertySetInfoE
+__ZTIN9configmgr9configapi19UpdateObjectFactoryE
+__ZTIN9configmgr9configapi21ReadOnlyObjectFactoryE
+__ZTIN9configmgr9configapi7FactoryE
+__ZTIN9configmgr9configapi8internal15SearchExactNameE
+__ZTIN9configmgr9OProviderE
+__ZTIN9configmgr9ValueNodeE
+__ZTIN9salhelper21SimpleReferenceObjectE
+;__ZTISt9bad_alloc
+;__ZTISt9exception
+
+
+IMPORTS
+__ZTIN10comphelper18OPropertyContainerE=configmg.__ZTIN10comphelper18OPropertyContainerE
+__ZTIN10comphelper24OPropertyContainerHelperE=configmg.__ZTIN10comphelper24OPropertyContainerHelperE
+__ZTIN10comphelper25OPropertyArrayUsageHelperIN9configmgr22OConfigurationProviderEEE=configmg.__ZTIN10comphelper25OPropertyArrayUsageHelperIN9configmgr22OConfigurationProviderEEE
+__ZTIN3com3sun4star13configuration17XTemplateInstanceE=configmg.__ZTIN3com3sun4star13configuration17XTemplateInstanceE
+__ZTIN3com3sun4star13configuration18XTemplateContainerE=configmg.__ZTIN3com3sun4star13configuration18XTemplateContainerE
+__ZTIN3com3sun4star13configuration29InvalidBootstrapFileExceptionE=configmg.__ZTIN3com3sun4star13configuration29InvalidBootstrapFileExceptionE
+__ZTIN3com3sun4star13configuration29MissingBootstrapFileExceptionE=configmg.__ZTIN3com3sun4star13configuration29MissingBootstrapFileExceptionE
+__ZTIN3com3sun4star13configuration31InstallationIncompleteExceptionE=configmg.__ZTIN3com3sun4star13configuration31InstallationIncompleteExceptionE
+__ZTIN3com3sun4star13configuration32CannotLoadConfigurationExceptionE=configmg.__ZTIN3com3sun4star13configuration32CannotLoadConfigurationExceptionE
+__ZTIN3com3sun4star13configuration7backend13XLayerHandlerE=configmg.__ZTIN3com3sun4star13configuration7backend13XLayerHandlerE
+__ZTIN3com3sun4star13configuration7backend14XLayerImporterE=configmg.__ZTIN3com3sun4star13configuration7backend14XLayerImporterE
+__ZTIN3com3sun4star13configuration7backend14XSchemaHandlerE=configmg.__ZTIN3com3sun4star13configuration7backend14XSchemaHandlerE
+__ZTIN3com3sun4star13configuration7backend14XUpdateHandlerE=configmg.__ZTIN3com3sun4star13configuration7backend14XUpdateHandlerE
+__ZTIN3com3sun4star13configuration7backend15XCompositeLayerE=configmg.__ZTIN3com3sun4star13configuration7backend15XCompositeLayerE
+__ZTIN3com3sun4star13configuration7backend15XSchemaSupplierE=configmg.__ZTIN3com3sun4star13configuration7backend15XSchemaSupplierE
+__ZTIN3com3sun4star13configuration7backend15XUpdatableLayerE=configmg.__ZTIN3com3sun4star13configuration7backend15XUpdatableLayerE
+__ZTIN3com3sun4star13configuration7backend16XBackendEntitiesE=configmg.__ZTIN3com3sun4star13configuration7backend16XBackendEntitiesE
+__ZTIN3com3sun4star13configuration7backend18XMultiLayerStratumE=configmg.__ZTIN3com3sun4star13configuration7backend18XMultiLayerStratumE
+__ZTIN3com3sun4star13configuration7backend19XSingleLayerStratumE=configmg.__ZTIN3com3sun4star13configuration7backend19XSingleLayerStratumE
+__ZTIN3com3sun4star13configuration7backend21BackendSetupExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend21BackendSetupExceptionE
+__ZTIN3com3sun4star13configuration7backend22BackendAccessExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend22BackendAccessExceptionE
+__ZTIN3com3sun4star13configuration7backend22CannotConnectExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend22CannotConnectExceptionE
+__ZTIN3com3sun4star13configuration7backend22MalformedDataExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend22MalformedDataExceptionE
+__ZTIN3com3sun4star13configuration7backend23ConnectionLostExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend23ConnectionLostExceptionE
+__ZTIN3com3sun4star13configuration7backend23XBackendChangesListenerE=configmg.__ZTIN3com3sun4star13configuration7backend23XBackendChangesListenerE
+__ZTIN3com3sun4star13configuration7backend23XBackendChangesNotifierE=configmg.__ZTIN3com3sun4star13configuration7backend23XBackendChangesNotifierE
+__ZTIN3com3sun4star13configuration7backend24StratumCreationExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend24StratumCreationExceptionE
+__ZTIN3com3sun4star13configuration7backend24XVersionedSchemaSupplierE=configmg.__ZTIN3com3sun4star13configuration7backend24XVersionedSchemaSupplierE
+__ZTIN3com3sun4star13configuration7backend29AuthenticationFailedExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend29AuthenticationFailedExceptionE
+__ZTIN3com3sun4star13configuration7backend33InsufficientAccessRightsExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend33InsufficientAccessRightsExceptionE
+__ZTIN3com3sun4star13configuration7backend39InvalidAuthenticationMechanismExceptionE=configmg.__ZTIN3com3sun4star13configuration7backend39InvalidAuthenticationMechanismExceptionE
+__ZTIN3com3sun4star13configuration7backend6XLayerE=configmg.__ZTIN3com3sun4star13configuration7backend6XLayerE
+__ZTIN3com3sun4star13configuration7backend7XSchemaE=configmg.__ZTIN3com3sun4star13configuration7backend7XSchemaE
+__ZTIN3com3sun4star13configuration7backend8XBackendE=configmg.__ZTIN3com3sun4star13configuration7backend8XBackendE
+__ZTIN3com3sun4star2io11IOExceptionE=configmg.__ZTIN3com3sun4star2io11IOExceptionE
+__ZTIN3com3sun4star2io12XInputStreamE=configmg.__ZTIN3com3sun4star2io12XInputStreamE
+__ZTIN3com3sun4star2io13XOutputStreamE=configmg.__ZTIN3com3sun4star2io13XOutputStreamE
+__ZTIN3com3sun4star2io15XActiveDataSinkE=configmg.__ZTIN3com3sun4star2io15XActiveDataSinkE
+__ZTIN3com3sun4star2io16XDataInputStreamE=configmg.__ZTIN3com3sun4star2io16XDataInputStreamE
+__ZTIN3com3sun4star2io17XActiveDataSourceE=configmg.__ZTIN3com3sun4star2io17XActiveDataSourceE
+__ZTIN3com3sun4star2io20WrongFormatExceptionE=configmg.__ZTIN3com3sun4star2io20WrongFormatExceptionE
+__ZTIN3com3sun4star2io21NotConnectedExceptionE=configmg.__ZTIN3com3sun4star2io21NotConnectedExceptionE
+__ZTIN3com3sun4star2io22UnexpectedEOFExceptionE=configmg.__ZTIN3com3sun4star2io22UnexpectedEOFExceptionE
+__ZTIN3com3sun4star2io27BufferSizeExceededExceptionE=configmg.__ZTIN3com3sun4star2io27BufferSizeExceededExceptionE
+__ZTIN3com3sun4star3uno10XInterfaceE=configmg.__ZTIN3com3sun4star3uno10XInterfaceE
+__ZTIN3com3sun4star3uno15XCurrentContextE=configmg.__ZTIN3com3sun4star3uno15XCurrentContextE
+;__ZTIN3com3sun4star3uno16RuntimeExceptionE=configmg.__ZTIN3com3sun4star3uno16RuntimeExceptionE
+__ZTIN3com3sun4star3uno17XComponentContextE=configmg.__ZTIN3com3sun4star3uno17XComponentContextE
+__ZTIN3com3sun4star3uno5XWeakE=configmg.__ZTIN3com3sun4star3uno5XWeakE
+;__ZTIN3com3sun4star3uno9ExceptionE=configmg.__ZTIN3com3sun4star3uno9ExceptionE
+__ZTIN3com3sun4star3xml3sax12SAXExceptionE=configmg.__ZTIN3com3sun4star3xml3sax12SAXExceptionE
+__ZTIN3com3sun4star3xml3sax14XAttributeListE=configmg.__ZTIN3com3sun4star3xml3sax14XAttributeListE
+__ZTIN3com3sun4star3xml3sax16XDocumentHandlerE=configmg.__ZTIN3com3sun4star3xml3sax16XDocumentHandlerE
+__ZTIN3com3sun4star4lang10XComponentE=configmg.__ZTIN3com3sun4star4lang10XComponentE
+__ZTIN3com3sun4star4lang10XUnoTunnelE=configmg.__ZTIN3com3sun4star4lang10XUnoTunnelE
+__ZTIN3com3sun4star4lang12XLocalizableE=configmg.__ZTIN3com3sun4star4lang12XLocalizableE
+__ZTIN3com3sun4star4lang12XServiceInfoE=configmg.__ZTIN3com3sun4star4lang12XServiceInfoE
+__ZTIN3com3sun4star4lang13XTypeProviderE=configmg.__ZTIN3com3sun4star4lang13XTypeProviderE
+__ZTIN3com3sun4star4lang14XEventListenerE=configmg.__ZTIN3com3sun4star4lang14XEventListenerE
+__ZTIN3com3sun4star4lang15XInitializationE=configmg.__ZTIN3com3sun4star4lang15XInitializationE
+__ZTIN3com3sun4star4lang17DisposedExceptionE=configmg.__ZTIN3com3sun4star4lang17DisposedExceptionE
+__ZTIN3com3sun4star4lang18NoSupportExceptionE=configmg.__ZTIN3com3sun4star4lang18NoSupportExceptionE
+__ZTIN3com3sun4star4lang20NullPointerExceptionE=configmg.__ZTIN3com3sun4star4lang20NullPointerExceptionE
+__ZTIN3com3sun4star4lang20XMultiServiceFactoryE=configmg.__ZTIN3com3sun4star4lang20XMultiServiceFactoryE
+__ZTIN3com3sun4star4lang21XSingleServiceFactoryE=configmg.__ZTIN3com3sun4star4lang21XSingleServiceFactoryE
+__ZTIN3com3sun4star4lang22IllegalAccessExceptionE=configmg.__ZTIN3com3sun4star4lang22IllegalAccessExceptionE
+__ZTIN3com3sun4star4lang22WrappedTargetExceptionE=configmg.__ZTIN3com3sun4star4lang22WrappedTargetExceptionE
+__ZTIN3com3sun4star4lang23XSingleComponentFactoryE=configmg.__ZTIN3com3sun4star4lang23XSingleComponentFactoryE
+__ZTIN3com3sun4star4lang24IllegalArgumentExceptionE=configmg.__ZTIN3com3sun4star4lang24IllegalArgumentExceptionE
+__ZTIN3com3sun4star4lang29ServiceNotRegisteredExceptionE=configmg.__ZTIN3com3sun4star4lang29ServiceNotRegisteredExceptionE
+__ZTIN3com3sun4star4lang29WrappedTargetRuntimeExceptionE=configmg.__ZTIN3com3sun4star4lang29WrappedTargetRuntimeExceptionE
+__ZTIN3com3sun4star4task17XInteractionAbortE=configmg.__ZTIN3com3sun4star4task17XInteractionAbortE
+__ZTIN3com3sun4star4task17XInteractionRetryE=configmg.__ZTIN3com3sun4star4task17XInteractionRetryE
+__ZTIN3com3sun4star4task19XInteractionApproveE=configmg.__ZTIN3com3sun4star4task19XInteractionApproveE
+__ZTIN3com3sun4star4task19XInteractionRequestE=configmg.__ZTIN3com3sun4star4task19XInteractionRequestE
+__ZTIN3com3sun4star4task22XInteractionDisapproveE=configmg.__ZTIN3com3sun4star4task22XInteractionDisapproveE
+__ZTIN3com3sun4star4task24XInteractionContinuationE=configmg.__ZTIN3com3sun4star4task24XInteractionContinuationE
+__ZTIN3com3sun4star4task4XJobE=configmg.__ZTIN3com3sun4star4task4XJobE
+__ZTIN3com3sun4star4util10XFlushableE=configmg.__ZTIN3com3sun4star4util10XFlushableE
+__ZTIN3com3sun4star4util12XRefreshableE=configmg.__ZTIN3com3sun4star4util12XRefreshableE
+__ZTIN3com3sun4star4util12XTimeStampedE=configmg.__ZTIN3com3sun4star4util12XTimeStampedE
+__ZTIN3com3sun4star4util13XChangesBatchE=configmg.__ZTIN3com3sun4star4util13XChangesBatchE
+__ZTIN3com3sun4star4util13XStringEscapeE=configmg.__ZTIN3com3sun4star4util13XStringEscapeE
+__ZTIN3com3sun4star4util16XChangesNotifierE=configmg.__ZTIN3com3sun4star4util16XChangesNotifierE
+__ZTIN3com3sun4star5beans10XExactNameE=configmg.__ZTIN3com3sun4star5beans10XExactNameE
+__ZTIN3com3sun4star5beans12XPropertySetE=configmg.__ZTIN3com3sun4star5beans12XPropertySetE
+__ZTIN3com3sun4star5beans14XPropertyStateE=configmg.__ZTIN3com3sun4star5beans14XPropertyStateE
+__ZTIN3com3sun4star5beans16XFastPropertySetE=configmg.__ZTIN3com3sun4star5beans16XFastPropertySetE
+__ZTIN3com3sun4star5beans16XPropertySetInfoE=configmg.__ZTIN3com3sun4star5beans16XPropertySetInfoE
+__ZTIN3com3sun4star5beans17XMultiPropertySetE=configmg.__ZTIN3com3sun4star5beans17XMultiPropertySetE
+__ZTIN3com3sun4star5beans18XPropertyWithStateE=configmg.__ZTIN3com3sun4star5beans18XPropertyWithStateE
+__ZTIN3com3sun4star5beans20XMultiPropertyStatesE=configmg.__ZTIN3com3sun4star5beans20XMultiPropertyStatesE
+__ZTIN3com3sun4star5beans21PropertyVetoExceptionE=configmg.__ZTIN3com3sun4star5beans21PropertyVetoExceptionE
+__ZTIN3com3sun4star5beans24UnknownPropertyExceptionE=configmg.__ZTIN3com3sun4star5beans24UnknownPropertyExceptionE
+__ZTIN3com3sun4star5beans24XHierarchicalPropertySetE=configmg.__ZTIN3com3sun4star5beans24XHierarchicalPropertySetE
+__ZTIN3com3sun4star5beans25XPropertiesChangeListenerE=configmg.__ZTIN3com3sun4star5beans25XPropertiesChangeListenerE
+__ZTIN3com3sun4star5beans29XMultiHierarchicalPropertySetE=configmg.__ZTIN3com3sun4star5beans29XMultiHierarchicalPropertySetE
+__ZTIN3com3sun4star5beans9XPropertyE=configmg.__ZTIN3com3sun4star5beans9XPropertyE
+__ZTIN3com3sun4star6script22CannotConvertExceptionE=configmg.__ZTIN3com3sun4star6script22CannotConvertExceptionE
+__ZTIN3com3sun4star8registry12XRegistryKeyE=configmg.__ZTIN3com3sun4star8registry12XRegistryKeyE
+__ZTIN3com3sun4star8registry15XSimpleRegistryE=configmg.__ZTIN3com3sun4star8registry15XSimpleRegistryE
+__ZTIN3com3sun4star8registry21InvalidValueExceptionE=configmg.__ZTIN3com3sun4star8registry21InvalidValueExceptionE
+__ZTIN3com3sun4star8registry22MergeConflictExceptionE=configmg.__ZTIN3com3sun4star8registry22MergeConflictExceptionE
+__ZTIN3com3sun4star8registry24InvalidRegistryExceptionE=configmg.__ZTIN3com3sun4star8registry24InvalidRegistryExceptionE
+__ZTIN3com3sun4star9container10XContainerE=configmg.__ZTIN3com3sun4star9container10XContainerE
+__ZTIN3com3sun4star9container11XNameAccessE=configmg.__ZTIN3com3sun4star9container11XNameAccessE
+__ZTIN3com3sun4star9container12XNameReplaceE=configmg.__ZTIN3com3sun4star9container12XNameReplaceE
+__ZTIN3com3sun4star9container14XElementAccessE=configmg.__ZTIN3com3sun4star9container14XElementAccessE
+__ZTIN3com3sun4star9container14XNameContainerE=configmg.__ZTIN3com3sun4star9container14XNameContainerE
+__ZTIN3com3sun4star9container17XHierarchicalNameE=configmg.__ZTIN3com3sun4star9container17XHierarchicalNameE
+__ZTIN3com3sun4star9container21ElementExistExceptionE=configmg.__ZTIN3com3sun4star9container21ElementExistExceptionE
+__ZTIN3com3sun4star9container22NoSuchElementExceptionE=configmg.__ZTIN3com3sun4star9container22NoSuchElementExceptionE
+__ZTIN3com3sun4star9container23XHierarchicalNameAccessE=configmg.__ZTIN3com3sun4star9container23XHierarchicalNameAccessE
+__ZTIN3com3sun4star9container6XChildE=configmg.__ZTIN3com3sun4star9container6XChildE
+__ZTIN3com3sun4star9container6XNamedE=configmg.__ZTIN3com3sun4star9container6XNamedE
+__ZTIN3vos10IReferenceE=configmg.__ZTIN3vos10IReferenceE
+__ZTIN3vos10OReferenceE=configmg.__ZTIN3vos10OReferenceE
+__ZTIN3vos6OTimerE=configmg.__ZTIN3vos6OTimerE
+__ZTIN3vos7OObjectE=configmg.__ZTIN3vos7OObjectE
+__ZTIN3vos7OThreadE=configmg.__ZTIN3vos7OThreadE
+__ZTIN3vos9IRunnableE=configmg.__ZTIN3vos9IRunnableE
+__ZTIN4cppu11ImplHelper2IN3com3sun4star8registry15XSimpleRegistryENS3_4util10XFlushableEEE=configmg.__ZTIN4cppu11ImplHelper2IN3com3sun4star8registry15XSimpleRegistryENS3_4util10XFlushableEEE
+__ZTIN4cppu11ImplHelper4IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XLocalizableENS3_4util12XRefreshableENS7_10XFlushableEEE=configmg.__ZTIN4cppu11ImplHelper4IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XLocalizableENS3_4util12XRefreshableENS7_10XFlushableEEE
+__ZTIN4cppu11ImplHelper6IN3com3sun4star5beans12XPropertySetENS4_17XMultiPropertySetENS4_24XHierarchicalPropertySetENS4_29XMultiHierarchicalPropertySetENS4_14XPropertyStateENS4_20XMultiPropertyStatesEEE=configmg.__ZTIN4cppu11ImplHelper6IN3com3sun4star5beans12XPropertySetENS4_17XMultiPropertySetENS4_24XHierarchicalPropertySetENS4_29XMultiHierarchicalPropertySetENS4_14XPropertyStateENS4_20XMultiPropertyStatesEEE
+__ZTIN4cppu11ImplHelper6IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyEEE=configmg.__ZTIN4cppu11ImplHelper6IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyEEE
+__ZTIN4cppu11ImplHelper9IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyENS9_16XPropertySetInfoENS3_13configuration18XTemplateCo!_yPkJc2=configmg.__ZTIN4cppu11ImplHelper9IN3com3sun4star9container11XNameAccessENS4_17XHierarchicalNameENS4_23XHierarchicalNameAccessENS4_10XContainerENS3_5beans10XExactNameENS9_9XPropertyENS9_16XPropertySetInfoENS3_13configuration18XTemplateCo!_yPkJc2
+__ZTIN4cppu11OWeakObjectE=configmg.__ZTIN4cppu11OWeakObjectE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend13XLayerHandlerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend13XLayerHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend14XSchemaHandlerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend14XSchemaHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend15XCompositeLayerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend15XCompositeLayerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend23XBackendChangesListenerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend23XBackendChangesListenerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend6XLayerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star13configuration7backend6XLayerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io12XInputStreamEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io12XInputStreamEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io13XOutputStreamEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io13XOutputStreamEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io16XDataInputStreamEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star2io16XDataInputStreamEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3uno15XCurrentContextEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3uno15XCurrentContextEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax14XAttributeListEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax14XAttributeListEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax16XDocumentHandlerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star3xml3sax16XDocumentHandlerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang14XEventListenerEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang14XEventListenerEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang23XSingleComponentFactoryEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4lang23XSingleComponentFactoryEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionAbortEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionAbortEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionRetryEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task17XInteractionRetryEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionApproveEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionApproveEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionRequestEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task19XInteractionRequestEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task22XInteractionDisapproveEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star4task22XInteractionDisapproveEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star5beans16XPropertySetInfoEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star5beans16XPropertySetInfoEEE
+__ZTIN4cppu15WeakImplHelper1IN3com3sun4star8registry12XRegistryKeyEEE=configmg.__ZTIN4cppu15WeakImplHelper1IN3com3sun4star8registry12XRegistryKeyEEE
+__ZTIN4cppu15WeakImplHelper2IN3com3sun4star13configuration7backend13XLayerHandlerENS5_6XLayerEEE=configmg.__ZTIN4cppu15WeakImplHelper2IN3com3sun4star13configuration7backend13XLayerHandlerENS5_6XLayerEEE
+__ZTIN4cppu15WeakImplHelper2IN3com3sun4star3uno15XCurrentContextENS3_4lang10XUnoTunnelEEE=configmg.__ZTIN4cppu15WeakImplHelper2IN3com3sun4star3uno15XCurrentContextENS3_4lang10XUnoTunnelEEE
+__ZTIN4cppu15WeakImplHelper2IN3com3sun4star4task4XJobENS3_4lang12XServiceInfoEEE=configmg.__ZTIN4cppu15WeakImplHelper2IN3com3sun4star4task4XJobENS3_4lang12XServiceInfoEEE
+__ZTIN4cppu15WeakImplHelper3IN3com3sun4star13configuration7backend14XLayerImporterENS3_4lang15XInitializationENS7_12XServiceInfoEEE=configmg.__ZTIN4cppu15WeakImplHelper3IN3com3sun4star13configuration7backend14XLayerImporterENS3_4lang15XInitializationENS7_12XServiceInfoEEE
+__ZTIN4cppu15WeakImplHelper3IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_13configuration7backend14XUpdateHandlerEEE=configmg.__ZTIN4cppu15WeakImplHelper3IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_13configuration7backend14XUpdateHandlerEEE
+__ZTIN4cppu15WeakImplHelper3IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang12XServiceInfoEEE=configmg.__ZTIN4cppu15WeakImplHelper3IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang12XServiceInfoEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend6XLayerEEE=configmg.__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend6XLayerEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend7XSchemaEEE=configmg.__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io15XActiveDataSinkENS3_13configuration7backend7XSchemaEEE
+__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io17XActiveDataSourceENS3_13configuration7backend13XLayerHandlerEEE=configmg.__ZTIN4cppu15WeakImplHelper4IN3com3sun4star4lang15XInitializationENS4_12XServiceInfoENS3_2io17XActiveDataSourceENS3_13configuration7backend13XLayerHandlerEEE
+__ZTIN4cppu15WeakImplHelper5IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableEEE=configmg.__ZTIN4cppu15WeakImplHelper5IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableEEE
+__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang10XComponentENS7_12XServiceInfoENS3_13configuration17XTemplateInstanceENS7_10XUnoTunnelEEE=configmg.__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XChildENS4_6XNamedENS3_4lang10XComponentENS7_12XServiceInfoENS3_13configuration17XTemplateInstanceENS7_10XUnoTunnelEEE
+__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableENS6_13XChangesBatchEEE=configmg.__ZTIN4cppu15WeakImplHelper6IN3com3sun4star9container6XNamedENS3_4util16XChangesNotifierENS3_4lang10XComponentENS8_12XServiceInfoENS8_12XLocalizableENS6_13XChangesBatchEEE
+__ZTIN4cppu18OPropertySetHelperE=configmg.__ZTIN4cppu18OPropertySetHelperE
+__ZTIN4cppu22ImplInheritanceHelper1IN9configmgr7localbe16LocalStratumBaseEN3com3sun4star13configuration7backend18XMultiLayerStratumEEE=configmg.__ZTIN4cppu22ImplInheritanceHelper1IN9configmgr7localbe16LocalStratumBaseEN3com3sun4star13configuration7backend18XMultiLayerStratumEEE
+__ZTIN4cppu22ImplInheritanceHelper1IN9configmgr7localbe16LocalStratumBaseEN3com3sun4star13configuration7backend19XSingleLayerStratumEEE=configmg.__ZTIN4cppu22ImplInheritanceHelper1IN9configmgr7localbe16LocalStratumBaseEN3com3sun4star13configuration7backend19XSingleLayerStratumEEE
+__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS6_4util12XTimeStampedEEE=configmg.__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend6XLayerENS6_4util12XTimeStampedEEE=configmg.__ZTIN4cppu22ImplInheritanceHelper2IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend6XLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu22ImplInheritanceHelper3IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS8_15XCompositeLayerENS6_4util12XTimeStampedEEE=configmg.__ZTIN4cppu22ImplInheritanceHelper3IN9configmgr7localbe19LayerPropertyHelperEN3com3sun4star13configuration7backend15XUpdatableLayerENS8_15XCompositeLayerENS6_4util12XTimeStampedEEE
+__ZTIN4cppu24WeakComponentImplHelper1IN3com3sun4star4lang12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper1IN3com3sun4star4lang12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper2IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper2IN3com3sun4star4lang20XMultiServiceFactoryENS4_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star13configuration7backend24XVersionedSchemaSupplierENS3_4lang15XInitializationENS7_12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star13configuration7backend24XVersionedSchemaSupplierENS3_4lang15XInitializationENS7_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star3uno17XComponentContextENS4_15XCurrentContextENS3_4lang12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star3uno17XComponentContextENS4_15XCurrentContextENS3_4lang12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star4lang15XInitializationENS3_13configuration7backend16XBackendEntitiesENS4_12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper3IN3com3sun4star4lang15XInitializationENS3_13configuration7backend16XBackendEntitiesENS4_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend15XSchemaSupplierENS5_18XMultiLayerStratumENS5_16XBackendEntitiesENS3_4lang15XInitializationENS9_12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend15XSchemaSupplierENS5_18XMultiLayerStratumENS5_16XBackendEntitiesENS3_4lang15XInitializationENS9_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_15XSchemaSupplierENS3_4lang15XInitializationENS9_12XServiceInfoEEE=configmg.__ZTIN4cppu24WeakComponentImplHelper5IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_15XSchemaSupplierENS3_4lang15XInitializationENS9_12XServiceInfoEEE
+__ZTIN4cppu24WeakComponentImplHelper7IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_24XVersionedSchemaSupplierENS5_23XBackendChangesNotifierENS5_23XBackendChangesListenerENS3_4lang15XInitializationEN!_7c1rO0=configmg.__ZTIN4cppu24WeakComponentImplHelper7IN3com3sun4star13configuration7backend8XBackendENS5_16XBackendEntitiesENS5_24XVersionedSchemaSupplierENS5_23XBackendChangesNotifierENS5_23XBackendChangesListenerENS3_4lang15XInitializationEN!_7c1rO0
+__ZTIN4cppu27WeakComponentImplHelperBaseE=configmg.__ZTIN4cppu27WeakComponentImplHelperBaseE
+__ZTIN9configmgr10BasicGroupE=configmg.__ZTIN9configmgr10BasicGroupE
+__ZTIN9configmgr10IInterfaceE=configmg.__ZTIN9configmgr10IInterfaceE
+__ZTIN9configmgr10NodeActionE=configmg.__ZTIN9configmgr10NodeActionE
+__ZTIN9configmgr10RefcountedE=configmg.__ZTIN9configmgr10RefcountedE
+__ZTIN9configmgr10RemoveNodeE=configmg.__ZTIN9configmgr10RemoveNodeE
+__ZTIN9configmgr10SearchNodeE=configmg.__ZTIN9configmgr10SearchNodeE
+__ZTIN9configmgr11ApplyUpdateE=configmg.__ZTIN9configmgr11ApplyUpdateE
+__ZTIN9configmgr11NoncopyableE=configmg.__ZTIN9configmgr11NoncopyableE
+__ZTIN9configmgr11TreeManagerE=configmg.__ZTIN9configmgr11TreeManagerE
+__ZTIN9configmgr11TreeUpdaterE=configmg.__ZTIN9configmgr11TreeUpdaterE
+__ZTIN9configmgr11ValueChangeE=configmg.__ZTIN9configmgr11ValueChangeE
+__ZTIN9configmgr12AdjustUpdateE=configmg.__ZTIN9configmgr12AdjustUpdateE
+__ZTIN9configmgr12CollectNamesE=configmg.__ZTIN9configmgr12CollectNamesE
+__ZTIN9configmgr12ITreeManagerE=configmg.__ZTIN9configmgr12ITreeManagerE
+__ZTIN9configmgr12ONameCreatorE=configmg.__ZTIN9configmgr12ONameCreatorE
+__ZTIN9configmgr12OPathCreatorINS_13configuration12AbsolutePathEEE=configmg.__ZTIN9configmgr12OPathCreatorINS_13configuration12AbsolutePathEEE
+__ZTIN9configmgr12OPathCreatorINS_13configuration12RelativePathEEE=configmg.__ZTIN9configmgr12OPathCreatorINS_13configuration12RelativePathEEE
+__ZTIN9configmgr13BasicValueSetE=configmg.__ZTIN9configmgr13BasicValueSetE
+__ZTIN9configmgr13INodeListenerE=configmg.__ZTIN9configmgr13INodeListenerE
+__ZTIN9configmgr13OInnerSetInfoE=configmg.__ZTIN9configmgr13OInnerSetInfoE
+__ZTIN9configmgr13OMergeChangesE=configmg.__ZTIN9configmgr13OMergeChangesE
+__ZTIN9configmgr13OProviderImplE=configmg.__ZTIN9configmgr13OProviderImplE
+__ZTIN9configmgr13PWMutexHolderE=configmg.__ZTIN9configmgr13PWMutexHolderE
+__ZTIN9configmgr13SubtreeChangeE=configmg.__ZTIN9configmgr13SubtreeChangeE
+__ZTIN9configmgr13configuration100_GLOBAL__N__ZN9configmgr13configuration12TemplateName18makeSimpleTypeNameERKN3com3sun4star3uno4TypeE12TypeDetectorE=configmg.__ZTIN9configmgr13configuration100_GLOBAL__N__ZN9configmgr13configuration12TemplateName18makeSimpleTypeNameERKN3com3sun4star3uno4TypeE12TypeDetectorE
+__ZTIN9configmgr13configuration11InvalidNameE=configmg.__ZTIN9configmgr13configuration11InvalidNameE
+__ZTIN9configmgr13configuration11NodeVisitorE=configmg.__ZTIN9configmgr13configuration11NodeVisitorE
+__ZTIN9configmgr13configuration11SetNodeImplE=configmg.__ZTIN9configmgr13configuration11SetNodeImplE
+__ZTIN9configmgr13configuration12RootTreeImplE=configmg.__ZTIN9configmgr13configuration12RootTreeImplE
+__ZTIN9configmgr13configuration12SetResetImplE=configmg.__ZTIN9configmgr13configuration12SetResetImplE
+__ZTIN9configmgr13configuration12TypeMismatchE=configmg.__ZTIN9configmgr13configuration12TypeMismatchE
+__ZTIN9configmgr13configuration13GroupNodeImplE=configmg.__ZTIN9configmgr13configuration13GroupNodeImplE
+__ZTIN9configmgr13configuration13SetChangeImplE=configmg.__ZTIN9configmgr13configuration13SetChangeImplE
+__ZTIN9configmgr13configuration13SetInsertImplE=configmg.__ZTIN9configmgr13configuration13SetInsertImplE
+__ZTIN9configmgr13configuration13SetRemoveImplE=configmg.__ZTIN9configmgr13configuration13SetRemoveImplE
+__ZTIN9configmgr13configuration14CollectChangesE=configmg.__ZTIN9configmgr13configuration14CollectChangesE
+__ZTIN9configmgr13configuration14NodeChangeImplE=configmg.__ZTIN9configmgr13configuration14NodeChangeImplE
+__ZTIN9configmgr13configuration14SetNodeVisitorE=configmg.__ZTIN9configmgr13configuration14SetNodeVisitorE
+__ZTIN9configmgr13configuration14SetReplaceImplE=configmg.__ZTIN9configmgr13configuration14SetReplaceImplE
+__ZTIN9configmgr13configuration14ValueResetImplE=configmg.__ZTIN9configmgr13configuration14ValueResetImplE
+__ZTIN9configmgr13configuration15ElementTreeImplE=configmg.__ZTIN9configmgr13configuration15ElementTreeImplE
+__ZTIN9configmgr13configuration15TreeImplBuilderE=configmg.__ZTIN9configmgr13configuration15TreeImplBuilderE
+__ZTIN9configmgr13configuration15ValueChangeImplE=configmg.__ZTIN9configmgr13configuration15ValueChangeImplE
+__ZTIN9configmgr13configuration15ValueMemberNode12DeferredImplE=configmg.__ZTIN9configmgr13configuration15ValueMemberNode12DeferredImplE
+__ZTIN9configmgr13configuration16ValueReplaceImplE=configmg.__ZTIN9configmgr13configuration16ValueReplaceImplE
+__ZTIN9configmgr13configuration18GroupMemberVisitorE=configmg.__ZTIN9configmgr13configuration18GroupMemberVisitorE
+__ZTIN9configmgr13configuration19ConstraintViolationE=configmg.__ZTIN9configmgr13configuration19ConstraintViolationE
+__ZTIN9configmgr13configuration19DeferredSetNodeImplE=configmg.__ZTIN9configmgr13configuration19DeferredSetNodeImplE
+__ZTIN9configmgr13configuration19WrappedUnoExceptionE=configmg.__ZTIN9configmgr13configuration19WrappedUnoExceptionE
+__ZTIN9configmgr13configuration20DefaultProviderProxyE=configmg.__ZTIN9configmgr13configuration20DefaultProviderProxyE
+__ZTIN9configmgr13configuration20SetElementChangeImplE=configmg.__ZTIN9configmgr13configuration20SetElementChangeImplE
+__ZTIN9configmgr13configuration20ValueElementNodeImplE=configmg.__ZTIN9configmgr13configuration20ValueElementNodeImplE
+__ZTIN9configmgr13configuration21DeferredGroupNodeImplE=configmg.__ZTIN9configmgr13configuration21DeferredGroupNodeImplE
+__ZTIN9configmgr13configuration21TemplateProvider_ImplE=configmg.__ZTIN9configmgr13configuration21TemplateProvider_ImplE
+__ZTIN9configmgr13configuration28SpecialTemplateProvider_ImplE=configmg.__ZTIN9configmgr13configuration28SpecialTemplateProvider_ImplE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv15CollectValueIDsE=configmg.__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv15CollectValueIDsE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv17SetVisitorAdapterE=configmg.__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv17SetVisitorAdapterE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv19GroupVisitorAdapterE=configmg.__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv19GroupVisitorAdapterE
+__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv21FindNonDefaultElementE=configmg.__ZTIN9configmgr13configuration55_GLOBAL__N__ZNK9configmgr13configuration4Tree7getViewEv21FindNonDefaultElementE
+__ZTIN9configmgr13configuration88_GLOBAL__N__ZN9configmgr13configuration17GroupUpdateHelperC2ERKNS0_4TreeERKNS0_7NodeRefE13NodeDefaulterE=configmg.__ZTIN9configmgr13configuration88_GLOBAL__N__ZN9configmgr13configuration17GroupUpdateHelperC2ERKNS0_4TreeERKNS0_7NodeRefE13NodeDefaulterE
+__ZTIN9configmgr13configuration8NodeImplE=configmg.__ZTIN9configmgr13configuration8NodeImplE
+__ZTIN9configmgr13configuration8TemplateE=configmg.__ZTIN9configmgr13configuration8TemplateE
+__ZTIN9configmgr13configuration8TreeImplE=configmg.__ZTIN9configmgr13configuration8TreeImplE
+__ZTIN9configmgr13configuration9ExceptionE=configmg.__ZTIN9configmgr13configuration9ExceptionE
+__ZTIN9configmgr14BasicSetAccessE=configmg.__ZTIN9configmgr14BasicSetAccessE
+__ZTIN9configmgr14ONodeConverterE=configmg.__ZTIN9configmgr14ONodeConverterE
+__ZTIN9configmgr14OStripDefaultsE=configmg.__ZTIN9configmgr14OStripDefaultsE
+__ZTIN9configmgr15BasicSetElementE=configmg.__ZTIN9configmgr15BasicSetElementE
+__ZTIN9configmgr15IConfigListenerE=configmg.__ZTIN9configmgr15IConfigListenerE
+__ZTIN9configmgr15OInnerGroupInfoE=configmg.__ZTIN9configmgr15OInnerGroupInfoE
+__ZTIN9configmgr15ProviderFactoryE=configmg.__ZTIN9configmgr15ProviderFactoryE
+__ZTIN9configmgr15ProviderWrapperE=configmg.__ZTIN9configmgr15ProviderWrapperE
+__ZTIN9configmgr16BasicGroupAccessE=configmg.__ZTIN9configmgr16BasicGroupAccessE
+__ZTIN9configmgr16BasicPropertySetE=configmg.__ZTIN9configmgr16BasicPropertySetE
+__ZTIN9configmgr16BasicRootElementE=configmg.__ZTIN9configmgr16BasicRootElementE
+__ZTIN9configmgr16BootstrapContextE=configmg.__ZTIN9configmgr16BootstrapContextE
+__ZTIN9configmgr16ChangeTreeActionE=configmg.__ZTIN9configmgr16ChangeTreeActionE
+__ZTIN9configmgr16ComponentContextE=configmg.__ZTIN9configmgr16ComponentContextE
+__ZTIN9configmgr16IDefaultProviderE=configmg.__ZTIN9configmgr16IDefaultProviderE
+__ZTIN9configmgr16ITemplateManagerE=configmg.__ZTIN9configmgr16ITemplateManagerE
+__ZTIN9configmgr16NodeModificationE=configmg.__ZTIN9configmgr16NodeModificationE
+__ZTIN9configmgr16OMergeRemoveNodeE=configmg.__ZTIN9configmgr16OMergeRemoveNodeE
+__ZTIN9configmgr16OPropagateLevelsE=configmg.__ZTIN9configmgr16OPropagateLevelsE
+__ZTIN9configmgr16UnoContextTunnel6TunnelE=configmg.__ZTIN9configmgr16UnoContextTunnel6TunnelE
+__ZTIN9configmgr17AttributeListImplE=configmg.__ZTIN9configmgr17AttributeListImplE
+__ZTIN9configmgr17BasicInnerElementE=configmg.__ZTIN9configmgr17BasicInnerElementE
+__ZTIN9configmgr17CacheClientAccessE=configmg.__ZTIN9configmgr17CacheClientAccessE
+__ZTIN9configmgr17ExtendedCacheDataE=configmg.__ZTIN9configmgr17ExtendedCacheDataE
+__ZTIN9configmgr17ExtendedCacheLineE=configmg.__ZTIN9configmgr17ExtendedCacheLineE
+__ZTIN9configmgr17OInnerGroupUpdateE=configmg.__ZTIN9configmgr17OInnerGroupUpdateE
+__ZTIN9configmgr17OMergeValueChangeE=configmg.__ZTIN9configmgr17OMergeValueChangeE
+__ZTIN9configmgr17TemplateCacheDataE=configmg.__ZTIN9configmgr17TemplateCacheDataE
+__ZTIN9configmgr18BasicUpdateElementE=configmg.__ZTIN9configmgr18BasicUpdateElementE
+__ZTIN9configmgr18CacheLoadingAccessE=configmg.__ZTIN9configmgr18CacheLoadingAccessE
+__ZTIN9configmgr18DisposingForwarderE=configmg.__ZTIN9configmgr18DisposingForwarderE
+__ZTIN9configmgr18IConfigBroadcasterE=configmg.__ZTIN9configmgr18IConfigBroadcasterE
+__ZTIN9configmgr18IConfigTreeManagerE=configmg.__ZTIN9configmgr18IConfigTreeManagerE
+__ZTIN9configmgr18OSetElementSetInfoE=configmg.__ZTIN9configmgr18OSetElementSetInfoE
+__ZTIN9configmgr19OInnerTreeSetUpdateE=configmg.__ZTIN9configmgr19OInnerTreeSetUpdateE
+__ZTIN9configmgr19ORootElementSetInfoE=configmg.__ZTIN9configmgr19ORootElementSetInfoE
+__ZTIN9configmgr20OCacheWriteScheduler5TimerE=configmg.__ZTIN9configmgr20OCacheWriteScheduler5TimerE
+__ZTIN9configmgr20OChangeActionCounterE=configmg.__ZTIN9configmgr20OChangeActionCounterE
+__ZTIN9configmgr20OCreateSubtreeActionE=configmg.__ZTIN9configmgr20OCreateSubtreeActionE
+__ZTIN9configmgr20OInnerValueSetUpdateE=configmg.__ZTIN9configmgr20OInnerValueSetUpdateE
+__ZTIN9configmgr20OMergeTreeChangeListE=configmg.__ZTIN9configmgr20OMergeTreeChangeListE
+__ZTIN9configmgr20OSetElementGroupInfoE=configmg.__ZTIN9configmgr20OSetElementGroupInfoE
+__ZTIN9configmgr20ServiceComponentImplE=configmg.__ZTIN9configmgr20ServiceComponentImplE
+__ZTIN9configmgr21ORootElementGroupInfoE=configmg.__ZTIN9configmgr21ORootElementGroupInfoE
+__ZTIN9configmgr21OSLInputStreamWrapperE=configmg.__ZTIN9configmgr21OSLInputStreamWrapperE
+__ZTIN9configmgr21OTreeDisposeScheduler5TimerE=configmg.__ZTIN9configmgr21OTreeDisposeScheduler5TimerE
+__ZTIN9configmgr21SubtreeChangeReferrerE=configmg.__ZTIN9configmgr21SubtreeChangeReferrerE
+__ZTIN9configmgr22ChangeTreeModificationE=configmg.__ZTIN9configmgr22ChangeTreeModificationE
+__ZTIN9configmgr22IConfigDefaultProviderE=configmg.__ZTIN9configmgr22IConfigDefaultProviderE
+__ZTIN9configmgr22IConfigTemplateManagerE=configmg.__ZTIN9configmgr22IConfigTemplateManagerE
+__ZTIN9configmgr22OConfigurationProviderE=configmg.__ZTIN9configmgr22OConfigurationProviderE
+__ZTIN9configmgr22OConfigurationRegistryE=configmg.__ZTIN9configmgr22OConfigurationRegistryE
+__ZTIN9configmgr22OSLOutputStreamWrapperE=configmg.__ZTIN9configmgr22OSLOutputStreamWrapperE
+__ZTIN9configmgr22OSetElementGroupUpdateE=configmg.__ZTIN9configmgr22OSetElementGroupUpdateE
+__ZTIN9configmgr23ConfigChangeBroadcasterE=configmg.__ZTIN9configmgr23ConfigChangeBroadcasterE
+__ZTIN9configmgr23IDefaultableTreeManagerE=configmg.__ZTIN9configmgr23IDefaultableTreeManagerE
+__ZTIN9configmgr23ORootElementGroupUpdateE=configmg.__ZTIN9configmgr23ORootElementGroupUpdateE
+__ZTIN9configmgr24OSetElementTreeSetUpdateE=configmg.__ZTIN9configmgr24OSetElementTreeSetUpdateE
+__ZTIN9configmgr25OConfigurationRegistryKeyE=configmg.__ZTIN9configmgr25OConfigurationRegistryKeyE
+__ZTIN9configmgr25ORootElementTreeSetUpdateE=configmg.__ZTIN9configmgr25ORootElementTreeSetUpdateE
+__ZTIN9configmgr25OSetElementValueSetUpdateE=configmg.__ZTIN9configmgr25OSetElementValueSetUpdateE
+__ZTIN9configmgr26OConfigurationProviderImplE=configmg.__ZTIN9configmgr26OConfigurationProviderImplE
+__ZTIN9configmgr26OProviderDisposingListenerE=configmg.__ZTIN9configmgr26OProviderDisposingListenerE
+__ZTIN9configmgr26ORootElementValueSetUpdateE=configmg.__ZTIN9configmgr26ORootElementValueSetUpdateE
+__ZTIN9configmgr26PropertiesFilteredNotifierE=configmg.__ZTIN9configmgr26PropertiesFilteredNotifierE
+__ZTIN9configmgr28ForwardTreeDifferenceBuilderE=configmg.__ZTIN9configmgr28ForwardTreeDifferenceBuilderE
+__ZTIN9configmgr29BackwardTreeDifferenceBuilderE=configmg.__ZTIN9configmgr29BackwardTreeDifferenceBuilderE
+__ZTIN9configmgr29OSLInputBufferedStreamWrapperE=configmg.__ZTIN9configmgr29OSLInputBufferedStreamWrapperE
+__ZTIN9configmgr3xml11BasicParserE=configmg.__ZTIN9configmgr3xml11BasicParserE
+__ZTIN9configmgr3xml11LayerParserE=configmg.__ZTIN9configmgr3xml11LayerParserE
+__ZTIN9configmgr3xml11LayerWriterE=configmg.__ZTIN9configmgr3xml11LayerWriterE
+__ZTIN9configmgr3xml12SchemaParserE=configmg.__ZTIN9configmgr3xml12SchemaParserE
+__ZTIN9configmgr3xml13ElementParser12BadValueTypeE=configmg.__ZTIN9configmgr3xml13ElementParser12BadValueTypeE
+__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend6XLayerEEE=configmg.__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend6XLayerEEE
+__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend7XSchemaEEE=configmg.__ZTIN9configmgr3xml13ParserServiceIN3com3sun4star13configuration7backend7XSchemaEEE
+__ZTIN9configmgr3xml13WriterServiceIN3com3sun4star13configuration7backend13XLayerHandlerEEE=configmg.__ZTIN9configmgr3xml13WriterServiceIN3com3sun4star13configuration7backend13XLayerHandlerEEE
+__ZTIN9configmgr3xml18LayerParserServiceE=configmg.__ZTIN9configmgr3xml18LayerParserServiceE
+__ZTIN9configmgr3xml19SchemaParserServiceE=configmg.__ZTIN9configmgr3xml19SchemaParserServiceE
+__ZTIN9configmgr4data10SetVisitorE=configmg.__ZTIN9configmgr4data10SetVisitorE
+__ZTIN9configmgr4data11NodeVisitorE=configmg.__ZTIN9configmgr4data11NodeVisitorE
+__ZTIN9configmgr4data11TreeSegment4ImplE=configmg.__ZTIN9configmgr4data11TreeSegment4ImplE
+__ZTIN9configmgr4data15TreeNodeBuilder12LinkSetNodesE=configmg.__ZTIN9configmgr4data15TreeNodeBuilder12LinkSetNodesE
+__ZTIN9configmgr4data20BasicDataTreeBuilderE=configmg.__ZTIN9configmgr4data20BasicDataTreeBuilderE
+__ZTIN9configmgr4data21ConvertingNodeBuilderE=configmg.__ZTIN9configmgr4data21ConvertingNodeBuilderE
+__ZTIN9configmgr4data21DataTreeDefaultMergerE=configmg.__ZTIN9configmgr4data21DataTreeDefaultMergerE
+__ZTIN9configmgr4data22CopyingDataTreeBuilder18ElementListBuilderE=configmg.__ZTIN9configmgr4data22CopyingDataTreeBuilder18ElementListBuilderE
+__ZTIN9configmgr4data22CopyingDataTreeBuilderE=configmg.__ZTIN9configmgr4data22CopyingDataTreeBuilderE
+__ZTIN9configmgr4data24ConvertingSubnodeBuilderE=configmg.__ZTIN9configmgr4data24ConvertingSubnodeBuilderE
+__ZTIN9configmgr4data25ConvertingDataTreeBuilder18ElementListBuilderE=configmg.__ZTIN9configmgr4data25ConvertingDataTreeBuilder18ElementListBuilderE
+__ZTIN9configmgr4data25ConvertingDataTreeBuilderE=configmg.__ZTIN9configmgr4data25ConvertingDataTreeBuilderE
+__ZTIN9configmgr4view11NodeFactoryE=configmg.__ZTIN9configmgr4view11NodeFactoryE
+__ZTIN9configmgr4view12ViewStrategyE=configmg.__ZTIN9configmgr4view12ViewStrategyE
+__ZTIN9configmgr4view18DirectViewStrategyE=configmg.__ZTIN9configmgr4view18DirectViewStrategyE
+__ZTIN9configmgr4view20DeferredViewStrategyE=configmg.__ZTIN9configmgr4view20DeferredViewStrategyE
+__ZTIN9configmgr4view20ReadOnlyViewStrategyE=configmg.__ZTIN9configmgr4view20ReadOnlyViewStrategyE
+__ZTIN9configmgr4view72_GLOBAL__N__ZNK9configmgr4view12ViewStrategy13checkInstanceERKNS0_4TreeE19GroupMemberDispatchE=configmg.__ZTIN9configmgr4view72_GLOBAL__N__ZNK9configmgr4view12ViewStrategy13checkInstanceERKNS0_4TreeE19GroupMemberDispatchE
+__ZTIN9configmgr5INodeE=configmg.__ZTIN9configmgr5INodeE
+__ZTIN9configmgr6ChangeE=configmg.__ZTIN9configmgr6ChangeE
+__ZTIN9configmgr6memory11HeapManagerE=configmg.__ZTIN9configmgr6memory11HeapManagerE
+__ZTIN9configmgr6memory14SimpleHeapLockE=configmg.__ZTIN9configmgr6memory14SimpleHeapLockE
+__ZTIN9configmgr6memory21SimpleHeapManagerBaseE=configmg.__ZTIN9configmgr6memory21SimpleHeapManagerBaseE
+__ZTIN9configmgr6memory25SimpleCheckingHeapManagerE=configmg.__ZTIN9configmgr6memory25SimpleCheckingHeapManagerE
+__ZTIN9configmgr6memory8DataLockE=configmg.__ZTIN9configmgr6memory8DataLockE
+__ZTIN9configmgr7AddNodeE=configmg.__ZTIN9configmgr7AddNodeE
+__ZTIN9configmgr7SubtreeE=configmg.__ZTIN9configmgr7SubtreeE
+__ZTIN9configmgr7backend10EmptyLayerE=configmg.__ZTIN9configmgr7backend10EmptyLayerE
+__ZTIN9configmgr7backend10NodeUpdateE=configmg.__ZTIN9configmgr7backend10NodeUpdateE
+__ZTIN9configmgr7backend11NamedUpdateE=configmg.__ZTIN9configmgr7backend11NamedUpdateE
+__ZTIN9configmgr7backend11NodeReplaceE=configmg.__ZTIN9configmgr7backend11NodeReplaceE
+__ZTIN9configmgr7backend11PropertyAddE=configmg.__ZTIN9configmgr7backend11PropertyAddE
+__ZTIN9configmgr7backend12ResultHolderINS0_12NodeInstanceEE10RCInstanceE=configmg.__ZTIN9configmgr7backend12ResultHolderINS0_12NodeInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend12ResultHolderINS0_16TemplateInstanceEE10RCInstanceE=configmg.__ZTIN9configmgr7backend12ResultHolderINS0_16TemplateInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend12ResultHolderINS0_17ComponentInstanceEE10RCInstanceE=configmg.__ZTIN9configmgr7backend12ResultHolderINS0_17ComponentInstanceEE10RCInstanceE
+__ZTIN9configmgr7backend13BackendAccessE=configmg.__ZTIN9configmgr7backend13BackendAccessE
+__ZTIN9configmgr7backend13ElementUpdateE=configmg.__ZTIN9configmgr7backend13ElementUpdateE
+__ZTIN9configmgr7backend13ImportServiceE=configmg.__ZTIN9configmgr7backend13ImportServiceE
+__ZTIN9configmgr7backend13PropertyResetE=configmg.__ZTIN9configmgr7backend13PropertyResetE
+__ZTIN9configmgr7backend13SchemaBuilderE=configmg.__ZTIN9configmgr7backend13SchemaBuilderE
+__ZTIN9configmgr7backend13UpdateServiceE=configmg.__ZTIN9configmgr7backend13UpdateServiceE
+__ZTIN9configmgr7backend14PropertyUpdateE=configmg.__ZTIN9configmgr7backend14PropertyUpdateE
+__ZTIN9configmgr7backend15CacheControllerE=configmg.__ZTIN9configmgr7backend15CacheControllerE
+__ZTIN9configmgr7backend16NodeModificationE=configmg.__ZTIN9configmgr7backend16NodeModificationE
+__ZTIN9configmgr7backend16UpdateDispatcherE=configmg.__ZTIN9configmgr7backend16UpdateDispatcherE
+__ZTIN9configmgr7backend17BasicUpdateMergerE=configmg.__ZTIN9configmgr7backend17BasicUpdateMergerE
+__ZTIN9configmgr7backend17BinaryReader_ImplE=configmg.__ZTIN9configmgr7backend17BinaryReader_ImplE
+__ZTIN9configmgr7backend17CopyImportServiceE=configmg.__ZTIN9configmgr7backend17CopyImportServiceE
+__ZTIN9configmgr7backend17INodeDataListenerE=configmg.__ZTIN9configmgr7backend17INodeDataListenerE
+__ZTIN9configmgr7backend17INodeDataProviderE=configmg.__ZTIN9configmgr7backend17INodeDataProviderE
+__ZTIN9configmgr7backend17LayerMergeHandlerE=configmg.__ZTIN9configmgr7backend17LayerMergeHandlerE
+__ZTIN9configmgr7backend17LayerUpdateMergerE=configmg.__ZTIN9configmgr7backend17LayerUpdateMergerE
+__ZTIN9configmgr7backend17RequireEmptyLayerE=configmg.__ZTIN9configmgr7backend17RequireEmptyLayerE
+__ZTIN9configmgr7backend18BasicImportHandlerE=configmg.__ZTIN9configmgr7backend18BasicImportHandlerE
+__ZTIN9configmgr7backend18BinaryWriteHandlerE=configmg.__ZTIN9configmgr7backend18BinaryWriteHandlerE
+__ZTIN9configmgr7backend18ImportMergeHandlerE=configmg.__ZTIN9configmgr7backend18ImportMergeHandlerE
+__ZTIN9configmgr7backend18LayerUpdateHandlerE=configmg.__ZTIN9configmgr7backend18LayerUpdateHandlerE
+__ZTIN9configmgr7backend18MergeImportServiceE=configmg.__ZTIN9configmgr7backend18MergeImportServiceE
+__ZTIN9configmgr7backend19ICachedDataListenerE=configmg.__ZTIN9configmgr7backend19ICachedDataListenerE
+__ZTIN9configmgr7backend19ICachedDataNotifierE=configmg.__ZTIN9configmgr7backend19ICachedDataNotifierE
+__ZTIN9configmgr7backend19ICachedDataProviderE=configmg.__ZTIN9configmgr7backend19ICachedDataProviderE
+__ZTIN9configmgr7backend19IDirectDataProviderE=configmg.__ZTIN9configmgr7backend19IDirectDataProviderE
+__ZTIN9configmgr7backend19IMergedDataProviderE=configmg.__ZTIN9configmgr7backend19IMergedDataProviderE
+__ZTIN9configmgr7backend19INodeUpdateProviderE=configmg.__ZTIN9configmgr7backend19INodeUpdateProviderE
+__ZTIN9configmgr7backend19LayerDefaultRemoverE=configmg.__ZTIN9configmgr7backend19LayerDefaultRemoverE
+__ZTIN9configmgr7backend19MultiStratumBackendE=configmg.__ZTIN9configmgr7backend19MultiStratumBackendE
+__ZTIN9configmgr7backend20IDefaultDataProviderE=configmg.__ZTIN9configmgr7backend20IDefaultDataProviderE
+__ZTIN9configmgr7backend20SingleBackendAdapterE=configmg.__ZTIN9configmgr7backend20SingleBackendAdapterE
+__ZTIN9configmgr7backend21BackendChangeNotifierE=configmg.__ZTIN9configmgr7backend21BackendChangeNotifierE
+__ZTIN9configmgr7backend21BackendStrataListenerE=configmg.__ZTIN9configmgr7backend21BackendStrataListenerE
+__ZTIN9configmgr7backend21IDataProviderMetaDataE=configmg.__ZTIN9configmgr7backend21IDataProviderMetaDataE
+__ZTIN9configmgr7backend21ITemplateDataProviderE=configmg.__ZTIN9configmgr7backend21ITemplateDataProviderE
+__ZTIN9configmgr7backend21OInvalidateTreeThreadE=configmg.__ZTIN9configmgr7backend21OInvalidateTreeThreadE
+__ZTIN9configmgr7backend22CacheChangeMulticasterE=configmg.__ZTIN9configmgr7backend22CacheChangeMulticasterE
+__ZTIN9configmgr7backend22IComponentDataProviderE=configmg.__ZTIN9configmgr7backend22IComponentDataProviderE
+__ZTIN9configmgr7backend8NodeDropE=configmg.__ZTIN9configmgr7backend8NodeDropE
+__ZTIN9configmgr7localbe16LocalDataStratumE=configmg.__ZTIN9configmgr7localbe16LocalDataStratumE
+__ZTIN9configmgr7localbe16LocalStratumBaseE=configmg.__ZTIN9configmgr7localbe16LocalStratumBaseE
+__ZTIN9configmgr7localbe17LocalMultiStratumE=configmg.__ZTIN9configmgr7localbe17LocalMultiStratumE
+__ZTIN9configmgr7localbe17LocalOutputStreamE=configmg.__ZTIN9configmgr7localbe17LocalOutputStreamE
+__ZTIN9configmgr7localbe18FlatLocalFileLayerE=configmg.__ZTIN9configmgr7localbe18FlatLocalFileLayerE
+__ZTIN9configmgr7localbe18LocalSingleBackendE=configmg.__ZTIN9configmgr7localbe18LocalSingleBackendE
+__ZTIN9configmgr7localbe18LocalSingleStratumE=configmg.__ZTIN9configmgr7localbe18LocalSingleStratumE
+__ZTIN9configmgr7localbe19BasicLocalFileLayerE=configmg.__ZTIN9configmgr7localbe19BasicLocalFileLayerE
+__ZTIN9configmgr7localbe19LayerPropertyHelperE=configmg.__ZTIN9configmgr7localbe19LayerPropertyHelperE
+__ZTIN9configmgr7localbe19LocalSchemaSupplierE=configmg.__ZTIN9configmgr7localbe19LocalSchemaSupplierE
+__ZTIN9configmgr7localbe20LocalReadonlyStratumE=configmg.__ZTIN9configmgr7localbe20LocalReadonlyStratumE
+__ZTIN9configmgr7localbe20LocalResourceStratumE=configmg.__ZTIN9configmgr7localbe20LocalResourceStratumE
+__ZTIN9configmgr7localbe20SimpleLocalFileLayerE=configmg.__ZTIN9configmgr7localbe20SimpleLocalFileLayerE
+__ZTIN9configmgr7localbe22LocalDataImportServiceE=configmg.__ZTIN9configmgr7localbe22LocalDataImportServiceE
+__ZTIN9configmgr7localbe22LocalSingleStratumBaseE=configmg.__ZTIN9configmgr7localbe22LocalSingleStratumBaseE
+__ZTIN9configmgr7localbe23CompositeLocalFileLayerE=configmg.__ZTIN9configmgr7localbe23CompositeLocalFileLayerE
+__ZTIN9configmgr7localbe23LocalStratumMutexHolderE=configmg.__ZTIN9configmgr7localbe23LocalStratumMutexHolderE
+__ZTIN9configmgr7localbe27FullCompositeLocalFileLayerE=configmg.__ZTIN9configmgr7localbe27FullCompositeLocalFileLayerE
+__ZTIN9configmgr7localbe28BasicCompositeLocalFileLayerE=configmg.__ZTIN9configmgr7localbe28BasicCompositeLocalFileLayerE
+__ZTIN9configmgr7localbe28LocalHierarchyBrowserServiceE=configmg.__ZTIN9configmgr7localbe28LocalHierarchyBrowserServiceE
+__ZTIN9configmgr8BasicSetE=configmg.__ZTIN9configmgr8BasicSetE
+__ZTIN9configmgr8ISubtreeE=configmg.__ZTIN9configmgr8ISubtreeE
+__ZTIN9configmgr8OOptionsE=configmg.__ZTIN9configmgr8OOptionsE
+__ZTIN9configmgr9CacheDataE=configmg.__ZTIN9configmgr9CacheDataE
+__ZTIN9configmgr9CacheLineE=configmg.__ZTIN9configmgr9CacheLineE
+__ZTIN9configmgr9OProviderE=configmg.__ZTIN9configmgr9OProviderE
+__ZTIN9configmgr9ValueNodeE=configmg.__ZTIN9configmgr9ValueNodeE
+__ZTIN9configmgr9apihelper15BroadcasterBaseE=configmg.__ZTIN9configmgr9apihelper15BroadcasterBaseE
+__ZTIN9configmgr9apihelper17PropertySetHelperE=configmg.__ZTIN9configmgr9apihelper17PropertySetHelperE
+__ZTIN9configmgr9apihelper18InteractionRequestE=configmg.__ZTIN9configmgr9apihelper18InteractionRequestE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionAbortEEE=configmg.__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionAbortEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionRetryEEE=configmg.__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task17XInteractionRetryEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task19XInteractionApproveEEE=configmg.__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task19XInteractionApproveEEE
+__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task22XInteractionDisapproveEEE=configmg.__ZTIN9configmgr9apihelper23InteractionContinuationIN3com3sun4star4task22XInteractionDisapproveEEE
+__ZTIN9configmgr9apihelper24SimpleInteractionRequestE=configmg.__ZTIN9configmgr9apihelper24SimpleInteractionRequestE
+__ZTIN9configmgr9apihelper31ConfigurationInteractionHandler7ContextE=configmg.__ZTIN9configmgr9apihelper31ConfigurationInteractionHandler7ContextE
+__ZTIN9configmgr9configapi10NodeAccessE=configmg.__ZTIN9configmgr9configapi10NodeAccessE
+__ZTIN9configmgr9configapi10SetElementE=configmg.__ZTIN9configmgr9configapi10SetElementE
+__ZTIN9configmgr9configapi11ApiTreeImpl16ComponentAdapterE=configmg.__ZTIN9configmgr9configapi11ApiTreeImpl16ComponentAdapterE
+__ZTIN9configmgr9configapi11Broadcaster4ImplE=configmg.__ZTIN9configmgr9configapi11Broadcaster4ImplE
+__ZTIN9configmgr9configapi11NodeElementE=configmg.__ZTIN9configmgr9configapi11NodeElementE
+__ZTIN9configmgr9configapi11OSetElementINS0_15NodeGroupAccessEEE=configmg.__ZTIN9configmgr9configapi11OSetElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_17NodeSetInfoAccessEEE=configmg.__ZTIN9configmgr9configapi11OSetElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_17NodeTreeSetAccessEEE=configmg.__ZTIN9configmgr9configapi11OSetElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_18NodeValueSetAccessEEE=configmg.__ZTIN9configmgr9configapi11OSetElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi11OSetElementINS0_19NodeGroupInfoAccessEEE=configmg.__ZTIN9configmgr9configapi11OSetElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi11RootElementE=configmg.__ZTIN9configmgr9configapi11RootElementE
+__ZTIN9configmgr9configapi11TreeElementE=configmg.__ZTIN9configmgr9configapi11TreeElementE
+__ZTIN9configmgr9configapi12InnerElementE=configmg.__ZTIN9configmgr9configapi12InnerElementE
+__ZTIN9configmgr9configapi12NotifierImplE=configmg.__ZTIN9configmgr9configapi12NotifierImplE
+__ZTIN9configmgr9configapi13NodeSetAccessE=configmg.__ZTIN9configmgr9configapi13NodeSetAccessE
+__ZTIN9configmgr9configapi13OInnerElementINS0_15NodeGroupAccessEEE=configmg.__ZTIN9configmgr9configapi13OInnerElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeSetInfoAccessEEE=configmg.__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeTreeSetAccessEEE=configmg.__ZTIN9configmgr9configapi13OInnerElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_18NodeValueSetAccessEEE=configmg.__ZTIN9configmgr9configapi13OInnerElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi13OInnerElementINS0_19NodeGroupInfoAccessEEE=configmg.__ZTIN9configmgr9configapi13OInnerElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi14ObjectRegistryE=configmg.__ZTIN9configmgr9configapi14ObjectRegistryE
+__ZTIN9configmgr9configapi15ApiRootTreeImpl12NodeListenerE=configmg.__ZTIN9configmgr9configapi15ApiRootTreeImpl12NodeListenerE
+__ZTIN9configmgr9configapi15NodeGroupAccessE=configmg.__ZTIN9configmgr9configapi15NodeGroupAccessE
+__ZTIN9configmgr9configapi16CollectNodeNamesE=configmg.__ZTIN9configmgr9configapi16CollectNodeNamesE
+__ZTIN9configmgr9configapi16OReadRootElementINS0_17NodeSetInfoAccessEEE=configmg.__ZTIN9configmgr9configapi16OReadRootElementINS0_17NodeSetInfoAccessEEE
+__ZTIN9configmgr9configapi16OReadRootElementINS0_19NodeGroupInfoAccessEEE=configmg.__ZTIN9configmgr9configapi16OReadRootElementINS0_19NodeGroupInfoAccessEEE
+__ZTIN9configmgr9configapi17CollectPropertiesE=configmg.__ZTIN9configmgr9configapi17CollectPropertiesE
+__ZTIN9configmgr9configapi17NodeSetInfoAccessE=configmg.__ZTIN9configmgr9configapi17NodeSetInfoAccessE
+__ZTIN9configmgr9configapi17NodeTreeSetAccessE=configmg.__ZTIN9configmgr9configapi17NodeTreeSetAccessE
+__ZTIN9configmgr9configapi17UpdateRootElementE=configmg.__ZTIN9configmgr9configapi17UpdateRootElementE
+__ZTIN9configmgr9configapi18NodeValueSetAccessE=configmg.__ZTIN9configmgr9configapi18NodeValueSetAccessE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_15NodeGroupAccessEEE=configmg.__ZTIN9configmgr9configapi18OUpdateRootElementINS0_15NodeGroupAccessEEE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_17NodeTreeSetAccessEEE=configmg.__ZTIN9configmgr9configapi18OUpdateRootElementINS0_17NodeTreeSetAccessEEE
+__ZTIN9configmgr9configapi18OUpdateRootElementINS0_18NodeValueSetAccessEEE=configmg.__ZTIN9configmgr9configapi18OUpdateRootElementINS0_18NodeValueSetAccessEEE
+__ZTIN9configmgr9configapi19CollectPropertyInfoE=configmg.__ZTIN9configmgr9configapi19CollectPropertyInfoE
+__ZTIN9configmgr9configapi19NodeGroupInfoAccessE=configmg.__ZTIN9configmgr9configapi19NodeGroupInfoAccessE
+__ZTIN9configmgr9configapi19NodePropertySetInfoE=configmg.__ZTIN9configmgr9configapi19NodePropertySetInfoE
+__ZTIN9configmgr9configapi19UpdateObjectFactoryE=configmg.__ZTIN9configmgr9configapi19UpdateObjectFactoryE
+__ZTIN9configmgr9configapi21ReadOnlyObjectFactoryE=configmg.__ZTIN9configmgr9configapi21ReadOnlyObjectFactoryE
+__ZTIN9configmgr9configapi7FactoryE=configmg.__ZTIN9configmgr9configapi7FactoryE
+__ZTIN9configmgr9configapi8internal15SearchExactNameE=configmg.__ZTIN9configmgr9configapi8internal15SearchExactNameE
+__ZTIN9salhelper21SimpleReferenceObjectE=configmg.__ZTIN9salhelper21SimpleReferenceObjectE
+
+EXPORTS
+__ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE
+__ZTIN3com3sun4star3ucb22InteractiveIOExceptionE
+__ZTIN3com3sun4star4task28ClassifiedInteractionRequestE
+__ZTIN3com3sun4star3ucb18NameClashExceptionE
+__ZTIN3com3sun4star3ucb27UnsupportedCommandExceptionE
+IMPORTS
+__ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE=ucpfile1.__ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE
+__ZTIN3com3sun4star3ucb22InteractiveIOExceptionE=ucpfile1.__ZTIN3com3sun4star3ucb22InteractiveIOExceptionE
+__ZTIN3com3sun4star4task28ClassifiedInteractionRequestE=ucpfile1.__ZTIN3com3sun4star4task28ClassifiedInteractionRequestE
+__ZTIN3com3sun4star3ucb18NameClashExceptionE=ucpfile1.__ZTIN3com3sun4star3ucb18NameClashExceptionE
+__ZTIN3com3sun4star3ucb27UnsupportedCommandExceptionE=ucpfile1.__ZTIN3com3sun4star3ucb27UnsupportedCommandExceptionE
+
+EXPORTS
+__ZTIN3com3sun4star3ucb34InteractiveBadTransferURLExceptionE
+IMPORTS
+__ZTIN3com3sun4star3ucb34InteractiveBadTransferURLExceptionE=ucb1.__ZTIN3com3sun4star3ucb34InteractiveBadTransferURLExceptionE
diff --git a/bridges/source/cpp_uno/gcc3_os2_intel/except.cxx b/bridges/source/cpp_uno/gcc3_os2_intel/except.cxx new file mode 100644 index 000000000000..cf2936917bc0 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/except.cxx @@ -0,0 +1,352 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <dlfcn.h> +#include <cxxabi.h> +#include <hash_map> + +#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" + +#ifdef TEST +#include "test/TestBridgeException.hpp" +#endif + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + +//================================================================================================== +//YD static handle to this dll, to allow rtti symbol lookup +static void* hmod; + +//================================================================================================== +//YD required to run test programs, because exe cannot export symbols! +#ifdef TEST +using namespace ::test; + +void dymmy_TestBridgeException() throw( ::test::TestBridgeException) +{ + throw TestBridgeException(); +} +#endif + +//================================================================================================== +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 hash_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 (hmod == NULL) + hmod = dlopen( "gcc3_uno.dll", 0); + + if (hmod) + rtti = (type_info *)dlsym( hmod, 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() +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 = 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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + diff --git a/bridges/source/cpp_uno/gcc3_os2_intel/makefile.mk b/bridges/source/cpp_uno/gcc3_os2_intel/makefile.mk new file mode 100644 index 000000000000..04abbabe664c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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)" == "GCCOS2Igcc3" + +.IF "$(cppu_no_leak)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF + +CFLAGSNOOPT=-O0 + +SLOFILES= \ + $(SLO)$/except.obj \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=defs$/gcc3_uno.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_os2_intel/share.hxx b/bridges/source/cpp_uno/gcc3_os2_intel/share.hxx new file mode 100644 index 000000000000..7529230fde94 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 ); +} diff --git a/bridges/source/cpp_uno/gcc3_os2_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_os2_intel/uno2cpp.cxx new file mode 100644 index 000000000000..f3f31236aea9 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_os2_intel/uno2cpp.cxx @@ -0,0 +1,454 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <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 +{ + +//================================================================================================== +// 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): +static void callVirtualMethod( + void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeClass eReturnType, + sal_Int32 * pStackLongs, + sal_Int32 nStackLongs ); +// __attribute__((noinline)); + +//================================================================================================== +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 + + /* figure out the address of the function we need to invoke */ + unsigned long * mfunc; // actual function to be invoked + int off; // offset used to find function + void (*ptr)(); + 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; + + 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" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "edx" ); + + (*ptr)(); + + asm volatile ( + // 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 occured... + *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 ); + } + } +} + +} } } 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..63457f7c7c95 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx @@ -0,0 +1,526 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.8 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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 *) +{} 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..a04a8f6c9214 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/except.cxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..0adc204a10f6 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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..7529230fde94 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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 ); +} 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..9bda6dcf417f --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_intel/uno2cpp.cxx @@ -0,0 +1,430 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.7 $ + * + * 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 occured... + *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 ); + } + } +} + +} } } 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..563991b05b56 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx @@ -0,0 +1,567 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.8 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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) + } 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..80884d013fdc --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/except.cxx @@ -0,0 +1,330 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..253abffc2bc5 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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..3ea6370f9a2c --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/share.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.4 $ + * + * 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; +} + +} 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..79ce6873fda9 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/uno2cpp.cxx @@ -0,0 +1,598 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.7 $ + * + * 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 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_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 occured... + *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 ); + } + } +} + +} } } 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..f9ffe7c1a46d --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/cpp2uno.cxx @@ -0,0 +1,521 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.5 $ + * + * 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 occured... + 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 occured... + { + // 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::createFromAscii("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::createFromAscii("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 *) +{} 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..75f8043d1ad3 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/dllinit.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: dllinit.cxx,v $ + * $Revision: 1.2 $ + * + * 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; +} 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..5285b709b7b5 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/except.cxx @@ -0,0 +1,317 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <hash_map> + +#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 hash_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 occured: %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_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + 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..242d21617d5e --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/makefile.mk @@ -0,0 +1,98 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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 + +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 +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(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..6aa69f0470e4 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/share.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: share.hxx,v $ + * $Revision: 1.3 $ + * + * 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 ); +} 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..26e05ba73b51 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/smallstruct.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: $ + * $Revision: $ + * + * 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)); +} + +} } } 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..e676778a8430 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/smallstruct.hxx @@ -0,0 +1,38 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: $ + * $Revision: $ + * + * 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); + +} } } 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..f6b6a1c6511d --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx @@ -0,0 +1,503 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.4 $ + * + * 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 occured... + *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 ); + } + } +} + +} } } 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..7b21b5d53f23 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -0,0 +1,491 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cpp2uno.cxx,v $ + * $Revision: 1.20 $ + * + * 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 occured... + 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 occured... + { + // 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; + 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 ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + 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 *) +{} 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..51624c3022ea --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/dllinit.cxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: dllinit.cxx,v $ + * $Revision: 1.3 $ + * + * 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; +} 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..fbdf13680aae --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx @@ -0,0 +1,635 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: except.cxx,v $ + * $Revision: 1.17 $ + * + * 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 <hash_map> +#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 hash_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 occured!") ), + Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); + return EXCEPTION_EXECUTE_HANDLER; +} + +} + +#pragma pack(pop) + 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..b044c09571ba --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.16 $ +# +# 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)" == "MSC" + +.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..f56ee1e8bc09 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: msci.hxx,v $ + * $Revision: 1.7 $ + * + * 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 ); + +} + 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..3fe4ed2e9f54 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx @@ -0,0 +1,468 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: uno2cpp.cxx,v $ + * $Revision: 1.14 $ + * + * 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 occured + *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 ); + } + } +} + +} } } diff --git a/bridges/source/cpp_uno/shared/bridge.cxx b/bridges/source/cpp_uno/shared/bridge.cxx new file mode 100644 index 000000000000..eac5d3f544ce --- /dev/null +++ b/bridges/source/cpp_uno/shared/bridge.cxx @@ -0,0 +1,229 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: bridge.cxx,v $ + * $Revision: 1.6 $ + * + * 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 ); +} + +} } } diff --git a/bridges/source/cpp_uno/shared/component.cxx b/bridges/source/cpp_uno/shared/component.cxx new file mode 100644 index 000000000000..a5da641a761c --- /dev/null +++ b/bridges/source/cpp_uno/shared/component.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: component.cxx,v $ + * $Revision: 1.8 $ + * + * 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_ENSURE( + 0, "### RuntimeException occured 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 ); +} + +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); +} + +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; + } +} + +} diff --git a/bridges/source/cpp_uno/shared/component.hxx b/bridges/source/cpp_uno/shared/component.hxx new file mode 100644 index 000000000000..0ef2665ddf32 --- /dev/null +++ b/bridges/source/cpp_uno/shared/component.hxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: component.hxx,v $ + * $Revision: 1.4 $ + * + * 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 diff --git a/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx new file mode 100644 index 000000000000..0863c629797b --- /dev/null +++ b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx @@ -0,0 +1,208 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: cppinterfaceproxy.cxx,v $ + * $Revision: 1.9 $ + * + * 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); +} + +} } } diff --git a/bridges/source/cpp_uno/shared/guardedarray.hxx b/bridges/source/cpp_uno/shared/guardedarray.hxx new file mode 100644 index 000000000000..670dc30ea9a9 --- /dev/null +++ b/bridges/source/cpp_uno/shared/guardedarray.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: guardedarray.hxx,v $ + * $Revision: 1.4 $ + * + * 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 diff --git a/bridges/source/cpp_uno/shared/makefile.mk b/bridges/source/cpp_uno/shared/makefile.mk new file mode 100644 index 000000000000..93a1c7512567 --- /dev/null +++ b/bridges/source/cpp_uno/shared/makefile.mk @@ -0,0 +1,57 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# 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..dcefd515da37 --- /dev/null +++ b/bridges/source/cpp_uno/shared/types.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.cxx,v $ + * $Revision: 1.7 $ + * + * 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; +} + +} } } diff --git a/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx new file mode 100644 index 000000000000..9b7a136979d6 --- /dev/null +++ b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx @@ -0,0 +1,145 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: unointerfaceproxy.cxx,v $ + * $Revision: 1.6 $ + * + * 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() +{} + +} } } diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx new file mode 100644 index 000000000000..3784f3959594 --- /dev/null +++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx @@ -0,0 +1,385 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtablefactory.cxx,v $ + * $Revision: 1.11 $ + * + * 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 OS2 +#define INCL_DOS +#define INCL_DOSMISC +#endif + +#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 <hash_map> +#include <new> +#include <vector> + +#if defined SAL_UNX +#include <unistd.h> +#include <string.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 +#elif defined SAL_OS2 +#define INCL_DOS +#define INCL_DOSMISC +#include <os2.h> +#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 + pagesize = getpagesize(); +#else + pagesize = sysconf(_SC_PAGESIZE); +#endif +#elif defined SAL_W32 + SYSTEM_INFO info; + GetSystemInfo(&info); + pagesize = info.dwPageSize; +#elif defined(SAL_OS2) + ULONG ulPageSize; + DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG)); + pagesize = (sal_Size)ulPageSize; +#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); +#elif defined(SAL_OS2) + p = 0; + DosAllocMem( &p, n, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY); +#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); +#elif defined(SAL_OS2) + (void) DosFreeMem( address); +#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 std::hash_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::createFromAscii("/tmp"); + + strDirectory += rtl::OUString::createFromAscii("/.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) + perror("creation of executable memory area failed"); + 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); + } +} diff --git a/bridges/source/cpp_uno/shared/vtables.cxx b/bridges/source/cpp_uno/shared/vtables.cxx new file mode 100644 index 000000000000..a18e04a8da71 --- /dev/null +++ b/bridges/source/cpp_uno/shared/vtables.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: vtables.cxx,v $ + * $Revision: 1.5 $ + * + * 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); +} + +} } } 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..6323a4f89710 --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_info_holder.java @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: JNI_info_holder.java,v $ + * $Revision: 1.7 $ + * + * 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..e5e55783454c --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/JNI_proxy.java @@ -0,0 +1,221 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: JNI_proxy.java,v $ + * $Revision: 1.9 $ + * + * 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..cc23338ac05b --- /dev/null +++ b/bridges/source/jni_uno/java/com/sun/star/bridges/jni_uno/makefile.mk @@ -0,0 +1,57 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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..90270d250608 --- /dev/null +++ b/bridges/source/jni_uno/jni_base.h @@ -0,0 +1,295 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_base.h,v $ + * $Revision: 1.14 $ + * + * 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_occured() 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_occured(); + } +} + +//______________________________________________________________________________ +inline bool JNI_context::assert_no_exception() const +{ + if (JNI_FALSE != m_env->ExceptionCheck()) + { + m_env->ExceptionClear(); + OSL_ENSURE( 0, "unexpected java exception occured!" ); + 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 diff --git a/bridges/source/jni_uno/jni_bridge.cxx b/bridges/source/jni_uno/jni_bridge.cxx new file mode 100644 index 000000000000..9f9a0487ca17 --- /dev/null +++ b/bridges/source/jni_uno/jni_bridge.cxx @@ -0,0 +1,572 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_bridge.cxx,v $ + * $Revision: 1.18 $ + * + * 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_ENSURE( 0, cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_ENSURE( + 0, + "[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_ENSURE( 0, cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_ENSURE( + 0, + "[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_occured() 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 occured, 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_ENSURE( 0, cstr_msg.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_ENSURE( + 0, + "[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 ); +} +} diff --git a/bridges/source/jni_uno/jni_bridge.h b/bridges/source/jni_uno/jni_bridge.h new file mode 100644 index 000000000000..b5bd963694c0 --- /dev/null +++ b/bridges/source/jni_uno/jni_bridge.h @@ -0,0 +1,127 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_bridge.h,v $ + * $Revision: 1.12 $ + * + * 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 diff --git a/bridges/source/jni_uno/jni_data.cxx b/bridges/source/jni_uno/jni_data.cxx new file mode 100644 index 000000000000..5d87eb0d1043 --- /dev/null +++ b/bridges/source/jni_uno/jni_data.cxx @@ -0,0 +1,2579 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_data.cxx,v $ + * $Revision: 1.23 $ + * + * 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: + *(jchar *) &pAny->pReserved = jni->CallCharMethodA( + java_data.l, m_jni_info->m_method_Character_charValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_BOOLEAN: + *(jboolean *) &pAny->pReserved = jni->CallBooleanMethodA( + java_data.l, m_jni_info->m_method_Boolean_booleanValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_BYTE: + *(jbyte *) &pAny->pReserved = jni->CallByteMethodA( + java_data.l, m_jni_info->m_method_Byte_byteValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(jshort *) &pAny->pReserved = jni->CallShortMethodA( + java_data.l, m_jni_info->m_method_Short_shortValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(jint *) &pAny->pReserved = jni->CallIntMethodA( + java_data.l, m_jni_info->m_method_Integer_intValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof (sal_Int64) <= sizeof (void *)) + { + *(jlong *) &pAny->pReserved = jni->CallLongMethodA( + java_data.l, m_jni_info->m_method_Long_longValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + } + 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 *)) + { + *(jfloat *) &pAny->pReserved = jni->CallFloatMethodA( + java_data.l, m_jni_info->m_method_Float_floatValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + } + 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 *)) + { + *(jdouble *) &pAny->pReserved = + jni->CallDoubleMethodA( + java_data.l, + m_jni_info->m_method_Double_doubleValue, 0 ); + jni.ensure_no_exception(); + pAny->pData = &pAny->pReserved; + } + 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; + jstring_to_ustring( + jni, (rtl_uString **)&pAny->pReserved, + (jstring) java_data.l ); + pAny->pData = &pAny->pReserved; + break; + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + map_to_uno( + jni, &pAny->pReserved, java_data, + value_td.get()->pWeakRef, 0, + false /* no assign */, false /* no out param */ ); + pAny->pData = &pAny->pReserved; + 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->pReserved; + 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->pReserved; + 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() ); + } + } +} + +} diff --git a/bridges/source/jni_uno/jni_helper.h b/bridges/source/jni_uno/jni_helper.h new file mode 100644 index 000000000000..46a79818795c --- /dev/null +++ b/bridges/source/jni_uno/jni_helper.h @@ -0,0 +1,165 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_helper.h,v $ + * $Revision: 1.10 $ + * + * 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 diff --git a/bridges/source/jni_uno/jni_info.cxx b/bridges/source/jni_uno/jni_info.cxx new file mode 100644 index 000000000000..941ac8a23a32 --- /dev/null +++ b/bridges/source/jni_uno/jni_info.cxx @@ -0,0 +1,999 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_info.cxx,v $ + * $Revision: 1.22 $ + * + * 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 ); +} + +} diff --git a/bridges/source/jni_uno/jni_info.h b/bridges/source/jni_uno/jni_info.h new file mode 100644 index 000000000000..bd211455c417 --- /dev/null +++ b/bridges/source/jni_uno/jni_info.h @@ -0,0 +1,378 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_info.h,v $ + * $Revision: 1.15 $ + * + * 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 <hash_map> + +#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 ::std::hash_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 diff --git a/bridges/source/jni_uno/jni_java2uno.cxx b/bridges/source/jni_uno/jni_java2uno.cxx new file mode 100644 index 000000000000..b3b4e5ab8b06 --- /dev/null +++ b/bridges/source/jni_uno/jni_java2uno.cxx @@ -0,0 +1,707 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_java2uno.cxx,v $ + * $Revision: 1.27 $ + * + * 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 "jni_finalizer.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 occured 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( 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 occured + { + // 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( 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_ENSURE( 0, 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_ENSURE( 0, 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( 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(); +} + +} diff --git a/bridges/source/jni_uno/jni_uno2java.cxx b/bridges/source/jni_uno/jni_uno2java.cxx new file mode 100644 index 000000000000..50c551427959 --- /dev/null +++ b/bridges/source/jni_uno/jni_uno2java.cxx @@ -0,0 +1,876 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: jni_uno2java.cxx,v $ + * $Revision: 1.24 $ + * + * 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 occured, 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 occured 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( 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( 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 occured + *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( 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_ENSURE( 0, cstr_msg2.getStr() ); +#else + (void) err; // unused +#endif + } + catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_ENSURE( + 0, + "[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( 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 occured + *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_ENSURE( 0, 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_ENSURE( 0, cstr_msg2.getStr() ); +#endif + } +} + +} +} diff --git a/bridges/source/jni_uno/makefile.mk b/bridges/source/jni_uno/makefile.mk new file mode 100644 index 000000000000..d020eb7e91a1 --- /dev/null +++ b/bridges/source/jni_uno/makefile.mk @@ -0,0 +1,89 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.9 $ +# +# 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 + +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..b19cbc829b66 --- /dev/null +++ b/bridges/source/jni_uno/nativethreadpool.cxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: nativethreadpool.cxx,v $ + * $Revision: 1.6 $ + * + * 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; +} diff --git a/bridges/source/remote/context/context.cxx b/bridges/source/remote/context/context.cxx new file mode 100644 index 000000000000..509f4b2a549c --- /dev/null +++ b/bridges/source/remote/context/context.cxx @@ -0,0 +1,502 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: context.cxx,v $ + * $Revision: 1.12 $ + * + * 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 <list> +#include <hash_map> +#include <utility> + +#include <osl/diagnose.h> +#include <osl/interlck.h> +#include <osl/mutex.hxx> + +#include "rtl/ustring.hxx" + +#include <bridges/remote/context.h> +#include <bridges/remote/remote.h> +#include <bridges/remote/connection.h> +#include <bridges/remote/counter.hxx> + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + +namespace { + +extern "C" typedef void * (SAL_CALL * MemAlloc)(sal_Size); + +} + +namespace remote_context +{ + +class remote_ContextImpl : + public remote_Context +{ +public: + remote_ContextImpl( remote_Connection *pConnection, + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *pProvider ); + ~remote_ContextImpl(); + + static void SAL_CALL thisAcquire( uno_Context * ); + static void SAL_CALL thisRelease( uno_Context * ); + static void * SAL_CALL thisQuery( uno_Context * , rtl_uString * ); + static void SAL_CALL thisAddDisposingListener( remote_Context * , remote_DisposingListener * ); + static void SAL_CALL thisRemoveDisposingListener( remote_Context *, remote_DisposingListener *); + static void SAL_CALL thisDispose( remote_Context *); +public: + oslInterlockedCount m_nRef; + sal_Bool m_bDisposed; + list < remote_DisposingListener * > m_lstListener; + Mutex m_mutex; +}; + + + + +struct equalOUString_Impl +{ + sal_Bool operator()(const OUString & s1, const OUString & s2) const + { return s1 == s2; } +}; + +struct hashOUString_Impl +{ + size_t operator()(const OUString & rName) const + { return rName.hashCode(); } +}; + +typedef hash_map +< + OUString, + void *, + hashOUString_Impl, + equalOUString_Impl +> +ContextMap; + +#if OSL_DEBUG_LEVEL > 1 +static MyCounter thisCounter( "DEBUG : Context" ); +#endif + +class ContextAdmin; + +ContextAdmin *g_pTheContext = 0; + + + +class ContextAdmin +{ +public: + static ContextAdmin *getInstance(); + + // listener administration + void addContextListener( remote_contextListenerFunc listener , void *pObject ); + void removeContextListener( remote_contextListenerFunc listener , void *pObject ); + + void fire( sal_Int32 nRemoteContextMode, + rtl_uString *sName, + rtl_uString *sDescription ); + + // context administration + uno_Context *createAndRegisterContext( + remote_Connection *pConnection, + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *pInstanceProvider ); + + void revokeContext( uno_Context *pRemoteContext ); + + uno_Context *get( rtl_uString *pHost ); + + rtl_uString ** getConnectionList( + sal_Int32 *pnStringCount, MemAlloc memAlloc ); + +private: + ::osl::Mutex m_mutex; + + ContextMap m_mapContext; + + typedef std::list< std::pair< remote_contextListenerFunc, void * > > List; + List m_lstListener; +}; + +ContextAdmin *ContextAdmin::getInstance() +{ + if( ! g_pTheContext ) { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + if( ! g_pTheContext ) { + //TODO This memory is leaked; see #i63473# for when this should be + // changed again: + g_pTheContext = new ContextAdmin; + } + } + return g_pTheContext; +} + +void ContextAdmin::addContextListener( remote_contextListenerFunc listener , void *pObject ) +{ + ::osl::MutexGuard guard( m_mutex ); + + m_lstListener.push_back( std::make_pair( listener, pObject ) ); +} + +void ContextAdmin::removeContextListener( remote_contextListenerFunc listener , void *pObject ) +{ + ::osl::MutexGuard guard( m_mutex ); + + for (List::iterator ii(m_lstListener.begin()); ii != m_lstListener.end(); + ++ii) + { + if (ii->first == listener && ii->second == pObject) { + m_lstListener.erase( ii ); + break; + } + } +} + +void ContextAdmin::fire( + sal_Int32 nRemoteContextMode, + rtl_uString *pName, + rtl_uString *sDescription ) +{ + List lst; + { + ::osl::MutexGuard guard( m_mutex ); + lst = m_lstListener; + } + for (List::iterator i(lst.begin()); i != lst.end(); ++i) { + (i->first)(i->second, nRemoteContextMode, pName, sDescription); + } +} + +uno_Context *ContextAdmin::createAndRegisterContext( remote_Connection *pConnection, + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *pInstanceProvider ) +{ + ::osl::MutexGuard guard( m_mutex ); + + uno_Context *pContext = get( pIdStr ); + if( pContext ) + { + pContext->release( pContext ); + return 0; + } + + remote_ContextImpl *p = new remote_ContextImpl( pConnection, + pIdStr, + pDescription, + pProtocol, + pInstanceProvider ); + + p->aBase.acquire( (uno_Context*) p ); + + m_mapContext[ OUString( pIdStr) ] = (void*) p; + + fire( REMOTE_CONTEXT_CREATE , pIdStr , pDescription ); + return ( uno_Context * )p; +} + + +void ContextAdmin::revokeContext( uno_Context *pRemoteContext ) +{ + ::osl::MutexGuard guard( m_mutex ); + + remote_ContextImpl *p = ( remote_ContextImpl * ) pRemoteContext; + + ContextMap::iterator ii = m_mapContext.find( p->m_pName ); + OSL_ASSERT( ii != m_mapContext.end() ); + m_mapContext.erase( ii ); + + fire( REMOTE_CONTEXT_DESTROY , p->m_pName , p->m_pDescription ); + +} + +uno_Context *ContextAdmin::get( rtl_uString *pHost ) +{ + ::osl::MutexGuard guard( m_mutex ); + + ContextMap::iterator ii = m_mapContext.find( OUString( (rtl_uString*)pHost ) ); + if( ii == m_mapContext.end() ) + { + return 0; + } + + uno_Context *p = ( uno_Context * ) (*ii).second; + p->acquire( p ); + return p; +} + + +rtl_uString ** ContextAdmin::getConnectionList( + sal_Int32 *pnStringCount, MemAlloc memAlloc ) +{ + ::osl::MutexGuard guard( m_mutex ); + + *pnStringCount = m_mapContext.size(); + rtl_uString **ppReturn = ( rtl_uString ** ) + memAlloc( sizeof( rtl_uString * ) * m_mapContext.size() ); + memset( ppReturn , 0 , sizeof( rtl_uString * ) * m_mapContext.size() ); + + sal_Int32 i = 0; + for( ContextMap::iterator ii = m_mapContext.begin() ; + ii != m_mapContext.end(); + ++ii, i++ ) + { + rtl_uString_assign( &( ppReturn[i] ), (*ii).first.pData ); + } + + return ppReturn; +} + + + +/***************************** + * remote_ContextImpl implementation + ****************************/ + + + +remote_ContextImpl::remote_ContextImpl( remote_Connection *pConnection , + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *pProvider ) : + m_nRef( 0 ), + m_bDisposed( sal_False ) +{ + m_pConnection = pConnection; + m_pConnection->acquire( m_pConnection ); + + m_pInstanceProvider = pProvider; + if( m_pInstanceProvider ) + { + m_pInstanceProvider->acquire( pProvider ); + } + + m_pName = pIdStr; + rtl_uString_acquire( m_pName ); + + m_pDescription = pDescription; + rtl_uString_acquire( m_pDescription ); + + m_pProtocol = pProtocol; + rtl_uString_acquire( pProtocol ); + + aBase.acquire = thisAcquire; + aBase.release = thisRelease; + addDisposingListener = thisAddDisposingListener; + removeDisposingListener = thisRemoveDisposingListener; + dispose = thisDispose; +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + +remote_ContextImpl::~remote_ContextImpl() +{ + // disposed must have been called + OSL_ASSERT( m_bDisposed ); + + rtl_uString_release( m_pName ); + rtl_uString_release( m_pDescription ); + rtl_uString_release( m_pProtocol ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif + +} + + +void remote_ContextImpl::thisAddDisposingListener( remote_Context *pRemoteC , + remote_DisposingListener *pListener ) +{ + remote_ContextImpl *pImpl = (remote_ContextImpl * ) pRemoteC; + + ::osl::MutexGuard guard( pImpl->m_mutex ); + + pListener->acquire( pListener ); + pImpl->m_lstListener.push_back( pListener ); +} + +void remote_ContextImpl::thisRemoveDisposingListener( remote_Context *pRemoteC, + remote_DisposingListener *pListener) +{ + remote_ContextImpl *pImpl = (remote_ContextImpl * ) pRemoteC; + MutexGuard guard( pImpl->m_mutex ); + + for( list< remote_DisposingListener * >::iterator ii = pImpl->m_lstListener.begin() ; + ii != pImpl->m_lstListener.end(); + ++ii ) + { + if( (*ii) == pListener ) + { + pImpl->m_lstListener.erase( ii ); + pListener->release( pListener ); + break; + } + } +} + +void remote_ContextImpl::thisDispose( remote_Context *pRemoteC ) +{ + remote_ContextImpl *pImpl = ( remote_ContextImpl * )pRemoteC; + + MutexGuard guard( pImpl->m_mutex ); + if( ! pImpl->m_bDisposed ) + { + pImpl->m_bDisposed = sal_True; + ContextAdmin::getInstance()->revokeContext( (uno_Context * ) pRemoteC ); + + if( pImpl->m_pInstanceProvider ) + { + pImpl->m_pInstanceProvider->release( pImpl->m_pInstanceProvider ); + pImpl->m_pInstanceProvider = 0; + } + + pImpl->m_pConnection->release( pImpl->m_pConnection ); + pImpl->m_pConnection = 0; + + list< remote_DisposingListener * > lst = pImpl->m_lstListener; + pImpl->m_lstListener.clear(); + + for( list < remote_DisposingListener * >::iterator ii = lst.begin(); + ii != lst.end(); + ++ii ) + { + (*ii)->disposing( (*ii) , pImpl->m_pName ); + (*ii)->release( (*ii) ); + } + + } +} + + + +void remote_ContextImpl::thisAcquire( uno_Context *pRemoteC ) +{ + remote_ContextImpl *p = SAL_REINTERPRET_CAST(remote_ContextImpl * ,pRemoteC ); + osl_incrementInterlockedCount( &(p->m_nRef) ); +} + +void remote_ContextImpl::thisRelease( uno_Context *pRemoteC ) +{ + remote_ContextImpl *p = SAL_REINTERPRET_CAST( remote_ContextImpl * , pRemoteC ); + if (! osl_decrementInterlockedCount( &(p->m_nRef) )) + { + // enshure, that this piece of code is not reentered + osl_incrementInterlockedCount( &(p->m_nRef) ); + + // dispose, if necessary + p->dispose( p ); + + // restore the counter + osl_decrementInterlockedCount( &(p->m_nRef) ); + + if( 0 == p->m_nRef ) + { + delete p; + } + else + { + // reanimated, but disposed ! + } + } +} + +void *remote_ContextImpl::thisQuery( uno_Context * , rtl_uString * ) +{ + return 0; +} + + +} // end namespace remote_context + + +using namespace remote_context; + +//----------------------- +// +// C-Interface +// +//----------------------- +extern "C" remote_Context * SAL_CALL +remote_getContext( rtl_uString *pIdString ) +{ + return (remote_Context *) ContextAdmin::getInstance()->get( pIdString ); +} + + + +extern "C" remote_Context * SAL_CALL +remote_createContext( remote_Connection *pConnection, + rtl_uString *pIdStr, + rtl_uString *pDescription, + rtl_uString *pProtocol, + remote_InstanceProvider *pProvider ) +{ + remote_ContextImpl *p = (remote_ContextImpl * ) + ContextAdmin::getInstance()->createAndRegisterContext( + pConnection , + pIdStr , + pDescription, + pProtocol, + pProvider ); + + return (remote_Context * )p; +} + + +extern "C" void SAL_CALL +remote_addContextListener( remote_contextListenerFunc listener, void *pObject ) +{ + ContextAdmin::getInstance()->addContextListener( listener , pObject ); +} + +extern "C" void SAL_CALL +remote_removeContextListener( remote_contextListenerFunc listener , void *pObject ) +{ + ContextAdmin::getInstance()->removeContextListener( listener , pObject ); +} + +extern "C" rtl_uString ** SAL_CALL +remote_getContextList( sal_Int32 *pnStringCount, MemAlloc memAlloc ) +{ + return ContextAdmin::getInstance()->getConnectionList( pnStringCount , memAlloc ); +} diff --git a/bridges/source/remote/context/exports.dxp b/bridges/source/remote/context/exports.dxp new file mode 100644 index 000000000000..dcef3c369b10 --- /dev/null +++ b/bridges/source/remote/context/exports.dxp @@ -0,0 +1,5 @@ +remote_getContext +remote_createContext +remote_getContextList +remote_removeContextListener +remote_addContextListener
\ No newline at end of file diff --git a/bridges/source/remote/context/makefile.mk b/bridges/source/remote/context/makefile.mk new file mode 100644 index 000000000000..4efb6214dc9e --- /dev/null +++ b/bridges/source/remote/context/makefile.mk @@ -0,0 +1,69 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# 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=rmcxt +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE + +UNIXVERSIONNAMES=UDK + +# --- Settings ----------------------------------------------------- +.INCLUDE : settings.mk +# ------------------------------------------------------------------ + +UNOUCRDEP=$(SOLARUCRDIR)$/uce.rdb +UNOUCRRDB=$(SOLARUCRDIR)$/uce.rdb + +SLOFILES= $(SLO)$/context.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS= \ + $(SALLIB) + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH=URELIB + +SHL1VERSIONMAP= $(TARGET).map + +DEF1NAME= $(SHL1TARGET) +#DEF1EXPORTFILE= exports.dxp + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/remote/context/rmcxt.map b/bridges/source/remote/context/rmcxt.map new file mode 100755 index 000000000000..182f6495ea9d --- /dev/null +++ b/bridges/source/remote/context/rmcxt.map @@ -0,0 +1,10 @@ +UDK_3_0_0 { + global: + remote_getContext; + remote_createContext; + remote_getContextList; + remote_removeContextListener; + remote_addContextListener; + local: + *; +}; diff --git a/bridges/source/remote/idl/corba.idl b/bridges/source/remote/idl/corba.idl new file mode 100644 index 000000000000..a3eb595781a2 --- /dev/null +++ b/bridges/source/remote/idl/corba.idl @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: corba.idl,v $ + * $Revision: 1.3 $ + * + * 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. + * + ************************************************************************/ +module com +{ +module sun +{ +module star +{ + +module corba +{ + + // CosBridging module + typedef unsigned long ObjectSystemID; + typedef sequence< byte > OpaqueData; + + struct OneThreadID + { + ObjectSystemID objSysID; + OpaqueData threadID; + }; + + typedef sequence<OneThreadID> ThreadIDs; + + struct LogicalThreadID // Service context + { + ThreadIDs IDs; + }; + + struct CorbaString8 + { + string theString; + }; + + struct CorbaUnion + { + long dummy; + }; + + struct ObjectKey + { + CorbaString8 sOid; + CorbaString8 sType; + }; + + enum TCKind + { + tk_null, tk_void, + tk_short, tk_long, tk_ushort, tk_ulong, + tk_float, tk_double, tk_boolean, tk_char, + tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref, + tk_struct, tk_union, tk_enum, tk_string, + tk_sequence, tk_array, tk_alias, tk_except, + tk_longlong, tk_ulonglong, tk_longdouble, + tk_wchar, tk_wstring, tk_fixed, + tk_value, tk_value_box, + tk_native, + tk_abstract_interface + }; +}; + +}; +}; +}; diff --git a/bridges/source/remote/static/helper.cxx b/bridges/source/remote/static/helper.cxx new file mode 100644 index 000000000000..c54075ce04a7 --- /dev/null +++ b/bridges/source/remote/static/helper.cxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: helper.cxx,v $ + * $Revision: 1.8 $ + * + * 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 <rtl/alloc.h> +#include <osl/diagnose.h> + +#include <bridges/remote/helper.hxx> + +#include <bridges/remote/stub.hxx> +#include <bridges/remote/proxy.hxx> +#include <bridges/remote/remote.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace bridges_remote +{ + +void SAL_CALL remote_createStub ( + remote_Interface **ppRemoteI, + rtl_uString *pOid , + typelib_TypeDescriptionReference *pTypeRef, + uno_Environment *pEnvRemote, + ReleaseRemoteCallbackFunc releaseRemoteCallback ) +{ + typelib_TypeDescription *pType = 0; + typelib_typedescriptionreference_getDescription( &pType, pTypeRef ); + + (void) pEnvRemote->pExtEnv->getRegisteredInterface( + pEnvRemote->pExtEnv, + (void **)ppRemoteI, + pOid, + (typelib_InterfaceTypeDescription* )pType ); + + if( *ppRemoteI ) + { + if( (*ppRemoteI)->acquire == acquireRemote2RemoteStub ) { + + if( releaseRemoteCallback ) + { + // use the callback handler, the bridge wants to send the call immeadiatly + releaseRemoteCallback( *ppRemoteI , pOid, pTypeRef , pEnvRemote ); + } + else + { + ((::bridges_remote::Remote2RemoteStub *)*ppRemoteI)->releaseRemote(); + } + } + else + { + // Uno2RemoteStub + // no release necessary + } + } + else + { + remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl; + *ppRemoteI = + new ::bridges_remote::Remote2RemoteStub( + pOid, + (typelib_InterfaceTypeDescription * ) pType, + pEnvRemote, + pImpl->m_sendRequest); + + // ppRemoteI may change during registration + pEnvRemote->pExtEnv->registerProxyInterface( + pEnvRemote->pExtEnv, + (void **) ppRemoteI, + freeRemote2RemoteStub, + pOid, + (typelib_InterfaceTypeDescription * ) pType ); + } + + typelib_typedescription_release( pType ); +} + +void SAL_CALL remote_sendQueryInterface( + uno_Environment *pEnvRemote, + remote_Interface **ppRemoteI, + rtl_uString *pOid , + typelib_TypeDescriptionReference *pTypeRef, + uno_Any **ppException + ) +{ + OSL_ASSERT( ppRemoteI ); + + typelib_InterfaceTypeDescription *pType = 0; + typelib_typedescriptionreference_getDescription( (typelib_TypeDescription ** )&pType, pTypeRef ); + + if( *ppRemoteI ) + { + (*ppRemoteI)->release( *ppRemoteI ); + (*ppRemoteI) = 0; + } + + remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl; + + Type type = ::getCppuType( (Reference < XInterface > *)0 ); + + // get type for queryInterface + OUString sCompleteMethodName = type.getTypeName(); + sCompleteMethodName += OUString::createFromAscii("::queryInterface"); + + typelib_InterfaceMemberTypeDescription *pMemberType = 0; + typelib_typedescription_getByName( + (typelib_TypeDescription **) &pMemberType, + sCompleteMethodName.pData ); + + OSL_ASSERT( pMemberType ); + + uno_Any anyInterface; + anyInterface.pType = 0; + anyInterface.pData = 0; + + void *pReturn = &anyInterface; + void *ppArgs[1]; + + ppArgs[0] = 0; + typelib_TypeDescriptionReference *pRef = 0; + typelib_typedescriptionreference_new( &pRef , + pType->aBase.eTypeClass, + pType->aBase.pTypeName); + + ppArgs[0] = &pRef; + +// uno_Any anyException; +// uno_Any *pAnyException = &anyException; + + // do the queryInterface + pImpl->m_sendRequest( + pEnvRemote, + (typelib_TypeDescription * ) pMemberType, + pOid, + pType, + pReturn, + ppArgs, + ppException ); + + + // now release everything + typelib_typedescriptionreference_release( pRef ); + typelib_typedescription_release( (typelib_TypeDescription * ) pMemberType ); + + if( *ppException ) + { + *ppRemoteI = 0; + } + else + { + // set out parameter + if( typelib_TypeClass_INTERFACE == anyInterface.pType->eTypeClass ) + { + *ppRemoteI = ( remote_Interface * ) anyInterface.pReserved; + } + typelib_typedescriptionreference_release( anyInterface.pType ); + } + + typelib_typedescription_release( (typelib_TypeDescription * ) pType ); +} + + +void SAL_CALL remote_retrieveOidFromProxy( + remote_Interface *pRemoteI, + rtl_uString **ppOid ) +{ + if( pRemoteI->acquire == acquireRemote2RemoteStub ) + { + // Remote2RemoteStub + ::bridges_remote::Remote2RemoteStub *pStub = (::bridges_remote::Remote2RemoteStub * ) pRemoteI; + rtl_uString_newFromString( ppOid , pStub->m_sOid.pData ); + } + else + { + // Uno2RemoteStub + ::bridges_remote::Uno2RemoteStub *pStub = (::bridges_remote::Uno2RemoteStub * ) pRemoteI; + rtl_uString_newFromString( ppOid , pStub->m_sOid.pData ); + pRemoteI->acquire( pRemoteI ); + } +} + +} diff --git a/bridges/source/remote/static/makefile.mk b/bridges/source/remote/static/makefile.mk new file mode 100644 index 000000000000..56237bb0a859 --- /dev/null +++ b/bridges/source/remote/static/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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=bridges_remote_static +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/proxy.obj \ + $(SLO)$/stub.obj \ + $(SLO)$/remote.obj \ + $(SLO)$/mapping.obj \ + $(SLO)$/helper.obj \ + $(SLO)$/remote_types.obj + +# Forte6 update 1 on Solaris Intel dies with internal compiler error +# on stub.cxx if optimization is on. Switch it off for now. +# To be reevaluated on compiler upgrade +.IF "$(OS)$(CPU)"=="SOLARISI" +NOOPTFILES=\ + $(SLO)$/stub.obj +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + diff --git a/bridges/source/remote/static/mapping.cxx b/bridges/source/remote/static/mapping.cxx new file mode 100644 index 000000000000..164481b5bfe0 --- /dev/null +++ b/bridges/source/remote/static/mapping.cxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: mapping.cxx,v $ + * $Revision: 1.5 $ + * + * 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/diagnose.h> + +#include <bridges/remote/proxy.hxx> +#include <bridges/remote/stub.hxx> +#include <bridges/remote/counter.hxx> +#include <bridges/remote/mapping.hxx> + +using namespace bridges_remote; + +extern "C" { + +static void SAL_CALL thisAcquire( uno_Mapping *pMap ) +{ + RemoteMapping *p = SAL_REINTERPRET_CAST( RemoteMapping * , pMap ); + if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) ) + { + if( remoteToUno == pMap->mapInterface ) + { + uno_registerMapping( &pMap , + freeRemoteMapping, + p->pEnvRemote , + p->pEnvUno , + p->m_sPurpose.pData ); + } + else + { + uno_registerMapping( &pMap , + freeRemoteMapping, + p->pEnvUno , + p->pEnvRemote , + p->m_sPurpose.pData ); + } + + } +} + +static void SAL_CALL thisRelease( uno_Mapping *pMap ) +{ + RemoteMapping *p = SAL_REINTERPRET_CAST( RemoteMapping * , pMap ); + if (! osl_decrementInterlockedCount( &(p->m_nRef) )) + { + uno_revokeMapping( pMap ); + } +} + +} + +namespace bridges_remote { + +void remoteToUno( uno_Mapping *pMapping, void **ppUnoI, void *pRemoteI, + typelib_InterfaceTypeDescription *pTypeDescr ) +{ + remote_Mapping *pRemoteMapping = ( remote_Mapping * ) pMapping; + + OSL_ASSERT( ppUnoI && pTypeDescr ); + if (*ppUnoI) + { + ((uno_Interface *)*ppUnoI)->release( (uno_Interface *)*ppUnoI ); + *ppUnoI = 0; + } + + if (pRemoteI && pTypeDescr) + { + // get object id of interface to be wrapped + rtl_uString * pOid = 0; + pRemoteMapping->pEnvRemote->pExtEnv->getObjectIdentifier( + pRemoteMapping->pEnvRemote->pExtEnv, + &pOid, + pRemoteI ); + + OSL_ASSERT(pOid); + if( ! pOid ) + { + return; + } + + // try to get any known interface from target environment + pRemoteMapping->pEnvUno->pExtEnv->getRegisteredInterface( + pRemoteMapping->pEnvUno->pExtEnv, + ppUnoI, + pOid, + pTypeDescr); + + if ( ! *ppUnoI) // already existing interface + { + // try to publish a new proxy; proxy may be exchanged during registration + *ppUnoI = new Remote2UnoProxy( + ( remote_Interface * ) pRemoteI, + pOid, + pTypeDescr , + pRemoteMapping->pEnvUno, + pRemoteMapping->pEnvRemote); + + pRemoteMapping->pEnvUno->pExtEnv->registerProxyInterface( + pRemoteMapping->pEnvUno->pExtEnv, + ppUnoI, + freeRemote2UnoProxy, + pOid, + pTypeDescr ); + + OSL_ASSERT( *ppUnoI ); + } + rtl_uString_release( pOid ); + } +} + +void unoToRemote( uno_Mapping *pMapping, void **ppRemoteI, void *pUnoI, + typelib_InterfaceTypeDescription *pTypeDescr ) +{ + remote_Mapping *pRemoteMapping = ( remote_Mapping * ) pMapping; + OSL_ASSERT( ppRemoteI && pTypeDescr ); + if (*ppRemoteI) + { + ((remote_Interface *)*ppRemoteI)->release( (remote_Interface *)*ppRemoteI); + *ppRemoteI = 0; + } + if (pUnoI && pTypeDescr) + { + // get object id of interface to be wrapped + rtl_uString * pOid = 0; + pRemoteMapping->pEnvUno->pExtEnv->getObjectIdentifier( + pRemoteMapping->pEnvUno->pExtEnv, + &pOid, + pUnoI ); + + OSL_ASSERT( pOid ); + if( ! pOid ) + { + return; + } + + pRemoteMapping->pEnvRemote->pExtEnv->getRegisteredInterface( + pRemoteMapping->pEnvRemote->pExtEnv, + (void**)ppRemoteI, + pOid, + pTypeDescr ); + + if( !*ppRemoteI ) + { + // try to publish a new proxy; + *ppRemoteI = new Uno2RemoteStub( + ( uno_Interface * ) pUnoI, + pOid, + pTypeDescr, + pRemoteMapping->pEnvUno, + pRemoteMapping->pEnvRemote ); + + // note : ppRemoteI may change during registration + pRemoteMapping->pEnvRemote->pExtEnv->registerProxyInterface( + pRemoteMapping->pEnvRemote->pExtEnv, + (void**) ppRemoteI, + freeUno2RemoteStub, + pOid, + pTypeDescr ); + } + + rtl_uString_release( pOid ); + } +} + +void freeRemoteMapping(uno_Mapping * mapping) { + delete reinterpret_cast< RemoteMapping * >(mapping); +} + +RemoteMapping::RemoteMapping( uno_Environment *pEnvUno_ , + uno_Environment *pEnvRemote_, + uno_MapInterfaceFunc func, + const ::rtl::OUString sPurpose) : + m_nRef( 1 ), + m_sPurpose( sPurpose ) +{ + pEnvUno = pEnvUno_; + pEnvRemote = pEnvRemote_; + + pEnvUno->acquire( pEnvUno ); + pEnvRemote->acquire( pEnvRemote ); + + aBase.mapInterface = func; + aBase.acquire = thisAcquire; + aBase.release = thisRelease; +} + +RemoteMapping::~RemoteMapping( ) +{ + pEnvUno->release( pEnvUno ); + pEnvRemote->release( pEnvRemote ); +} + +} diff --git a/bridges/source/remote/static/proxy.cxx b/bridges/source/remote/static/proxy.cxx new file mode 100644 index 000000000000..6cfd9c11e9fb --- /dev/null +++ b/bridges/source/remote/static/proxy.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: proxy.cxx,v $ + * $Revision: 1.13 $ + * + * 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 <bridges/remote/proxy.hxx> +#include <bridges/remote/context.h> + +#include <uno/data.h> +#include <uno/mapping.hxx> +#include <uno/environment.h> + +#include <com/sun/star/uno/Any.hxx> + +#include <bridges/remote/bridgeimpl.hxx> + +#include "remote_types.hxx" + +#if OSL_DEBUG_LEVEL > 1 +#include <bridges/remote/counter.hxx> +static MyCounter thisCounter( "DEBUG : Remote2UnoProxy"); +#endif + +using namespace ::bridges_remote; +using namespace ::com::sun::star::uno; + +extern "C" { + +void SAL_CALL remote_release( void *pRemoteI ) +{ + ((remote_Interface * )pRemoteI)->release( (remote_Interface * ) pRemoteI ); +} + +} + +namespace bridges_remote { + +void freeRemote2UnoProxy(uno_ExtEnvironment *, void * proxy) { + delete static_cast< Remote2UnoProxy * >(proxy); +} + +void acquireRemote2UnoProxy( uno_Interface *pThis ) +{ + Remote2UnoProxy *p = ( Remote2UnoProxy * ) pThis; + if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) ) + { + p->m_pEnvUno->pExtEnv->registerProxyInterface( + p->m_pEnvUno->pExtEnv, + (void**)&pThis, + freeRemote2UnoProxy, + p->m_sOid.pData, + p->m_pType ); + OSL_ASSERT( (uno_Interface *)p == pThis ); + } +} + +void releaseRemote2UnoProxy( uno_Interface *pThis ) +{ + Remote2UnoProxy *p = ( Remote2UnoProxy * ) pThis; + if ( 0 == osl_decrementInterlockedCount( &(p->m_nRef) )) + { + p->m_pEnvUno->pExtEnv->revokeInterface( p->m_pEnvUno->pExtEnv, p ); + } +} + +void SAL_CALL dispatchRemote2UnoProxy( + uno_Interface * pUnoI, + typelib_TypeDescription const * pType, + void * pReturn, + void * ppArgs[], + uno_Any ** ppException ) +{ + Remote2UnoProxy *p = ( Remote2UnoProxy * ) pUnoI; + RemoteThreadCounter counter( p->m_pEnvRemote ); + + typelib_InterfaceMethodTypeDescription *pMethodType = 0; + typelib_InterfaceAttributeTypeDescription *pAttributeType = 0; + typelib_TypeDescription *pReturnType = 0; + typelib_TypeDescription **ppArgType = 0; + sal_Int32 nArgCount = 0; + sal_Bool *pbIsIn = 0; + sal_Bool *pbIsOut = 0; + sal_Bool *pbConversionNeeded = 0; + sal_Bool bConversionNeededForReturn = 0; + + //-------------------------------- + // Collect all needed types ! + //-------------------------------- + if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pType->eTypeClass ) + { + pAttributeType = ( typelib_InterfaceAttributeTypeDescription * ) pType; + if( pReturn ) + { + TYPELIB_DANGER_GET( &pReturnType , pAttributeType->pAttributeTypeRef ); + bConversionNeededForReturn = remote_relatesToInterface( pReturnType ); + } + else + { + nArgCount = 1; + ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) ); + pbIsIn = ( sal_Bool * ) alloca( sizeof( sal_Bool ) ); + pbIsOut = ( sal_Bool * ) alloca( sizeof( sal_Bool ) ); + pbConversionNeeded = ( sal_Bool *) alloca( sizeof( sal_Bool ) ); + + pbIsIn[0] = sal_True; + pbIsOut[0] = sal_False; + ppArgType[0] = 0; + TYPELIB_DANGER_GET( &( ppArgType[0] ) , pAttributeType->pAttributeTypeRef ); + pbConversionNeeded[0] = remote_relatesToInterface( ppArgType[0] ); + + } + } + if( typelib_TypeClass_INTERFACE_METHOD == pType->eTypeClass ) + { + pMethodType = ( typelib_InterfaceMethodTypeDescription * ) pType; + TYPELIB_DANGER_GET( &pReturnType , pMethodType->pReturnTypeRef ); + bConversionNeededForReturn = remote_relatesToInterface( pReturnType ); + nArgCount = pMethodType->nParams; + ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) * nArgCount ); + pbIsIn = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount ); + pbIsOut = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount ); + pbConversionNeeded = ( sal_Bool *) alloca( sizeof( sal_Bool ) * nArgCount ); + sal_Int32 i; + for( i = 0 ; i < nArgCount ; i ++ ) + { + ppArgType[i] = 0; + TYPELIB_DANGER_GET( & (ppArgType[i]) , pMethodType->pParams[i].pTypeRef ); + pbIsIn[i] = pMethodType->pParams[i].bIn; + pbIsOut[i] = pMethodType->pParams[i].bOut; + pbConversionNeeded[i] = remote_relatesToInterface( ppArgType[i] ); + } + } + + void *pRemoteReturn = 0; + if( pReturnType ) + { + if( bConversionNeededForReturn ) + { + pRemoteReturn = alloca( pReturnType->nSize ); + } + else + { + pRemoteReturn = pReturn; + } + } + + void ** ppRemoteArgs = 0; + if( nArgCount ) + { + ppRemoteArgs = (void**) alloca( sizeof( void * ) * nArgCount ); + } + + sal_Int32 i; + for( i = 0 ; i < nArgCount ; i ++ ) + { + if( pbConversionNeeded[i] ) + { + ppRemoteArgs[i] = alloca( ppArgType[i]->nSize ); + + if( pbIsIn[i] ) { + uno_copyAndConvertData( + ppRemoteArgs[i], + ppArgs[i], + ppArgType[i], + p->m_mapUno2Remote.get() ); + } + } + else + { + ppRemoteArgs[i] = ppArgs[i]; + } + } + + uno_Any any; + uno_Any *pAny = &any; + + p->m_pRemoteI->pDispatcher( p->m_pRemoteI, + pType, + pRemoteReturn, + ppRemoteArgs, + &pAny ); + + if( ! pAny ) + { + if( pReturn && bConversionNeededForReturn ) + { + uno_copyAndConvertData( + pReturn , + pRemoteReturn, + pReturnType, + p->m_mapRemote2Uno.get() ); + uno_destructData( pRemoteReturn , pReturnType , remote_release ); + } + + sal_Int32 j; + for( j = 0 ; j < nArgCount ; j ++ ) + { + if( pbConversionNeeded[j] ) + { + if( pbIsIn[j] ) { + if( pbIsOut[j] ) { + uno_destructData( ppArgs[j] , + ppArgType[j] , + 0 ); + uno_copyAndConvertData( ppArgs[j] , + ppRemoteArgs[j], + ppArgType[j], + p->m_mapRemote2Uno.get() ); + } + } + else // pure out + { + uno_copyAndConvertData( ppArgs[j] , + ppRemoteArgs[j], + ppArgType[j], + p->m_mapRemote2Uno.get() ); + } + uno_destructData( ppRemoteArgs[j], + ppArgType[j], + remote_release ); + } + } + *ppException = 0; + } + else + { + // ----------------------- + // an exception occured + // ----------------------- + typelib_TypeDescription *pAnyType = 0; + getCppuType( (::com::sun::star::uno::Any*) 0 ).getDescription( &pAnyType ); + uno_copyAndConvertData( *ppException , + pAny , + pAnyType, + p->m_mapRemote2Uno.get() ); + uno_destructData( pAny , pAnyType , remote_release ); + typelib_typedescription_release( pAnyType ); + + // destruct remote in parameters ( out parameters have not been constructed ) + for( i = 0 ; i < nArgCount ; i ++ ) + { + if( pbConversionNeeded[i] && pbIsIn[i] ) + { + uno_destructData( ppRemoteArgs[i], + ppArgType[i], + remote_release ); + } + } + } + + //-------------------------- + // release all acquired types + //-------------------------- + if( pReturnType ) + { + TYPELIB_DANGER_RELEASE( pReturnType ); + } + for( i = 0 ; i < nArgCount ; i ++ ) + { + TYPELIB_DANGER_RELEASE( ppArgType[ i] ); + } + +} + +Remote2UnoProxy::Remote2UnoProxy( remote_Interface *pRemoteI, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType, + uno_Environment *pEnvUno, + uno_Environment *pEnvRemote ) : + m_sOid( pOid ), + m_pType( pType ), + m_pRemoteI( pRemoteI ), + m_pEnvUno( pEnvUno ), + m_pEnvRemote( pEnvRemote ), + m_mapRemote2Uno( pEnvRemote, pEnvUno ), + m_mapUno2Remote( pEnvUno , pEnvRemote ), + m_nRef( 1 ) +{ + typelib_typedescription_acquire( (typelib_TypeDescription * ) m_pType ); + m_pEnvUno->acquire( m_pEnvUno ); + m_pEnvRemote->acquire( m_pEnvRemote ); + + acquire = acquireRemote2UnoProxy; + release = releaseRemote2UnoProxy; + pDispatcher = dispatchRemote2UnoProxy; + + m_pEnvRemote->pExtEnv->registerInterface( + m_pEnvRemote->pExtEnv, + (void**)&m_pRemoteI, + m_sOid.pData, + m_pType ); + m_pRemoteI->acquire( m_pRemoteI ); + +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + +Remote2UnoProxy::~Remote2UnoProxy() +{ + // revoke external ref (oid) + m_pEnvRemote->pExtEnv->revokeInterface( m_pEnvRemote->pExtEnv , m_pRemoteI ); + + typelib_typedescription_release( (typelib_TypeDescription * )m_pType ); + m_pRemoteI->release( m_pRemoteI ); + m_pEnvUno->release( m_pEnvUno ); + m_pEnvRemote->release( m_pEnvRemote ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + +} // end namespace bridge_remote diff --git a/bridges/source/remote/static/remote.cxx b/bridges/source/remote/static/remote.cxx new file mode 100644 index 000000000000..ed8b1dbc9d59 --- /dev/null +++ b/bridges/source/remote/static/remote.cxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: remote.cxx,v $ + * $Revision: 1.10 $ + * + * 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/remote/remote.hxx> +#include <bridges/remote/counter.hxx> + +#if OSL_DEBUG_LEVEL > 1 +static MyCounter thisCounter( "DEBUG : Remote2RemoteStub"); +#endif + +using namespace bridges_remote; + +extern "C" { + +static void SAL_CALL thisRelease( remote_Interface *pThis ) +{ + Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis; + if (! osl_decrementInterlockedCount( &(p->m_nRef) )) + { + p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis ); + + } +} + +static void SAL_CALL thisDispatch( + remote_Interface * pRemoteI, + typelib_TypeDescription const * pMemberType, + void * pReturn, + void * pArgs[], + uno_Any ** ppException ) +{ + Remote2RemoteStub *pThis = ( Remote2RemoteStub * ) pRemoteI; + + pThis->m_dispatch( pThis->m_pEnvRemote, + pMemberType, + pThis->m_sOid.pData, + pThis->m_pType, + pReturn, + pArgs, + ppException ); +} + +} + +namespace bridges_remote { + +void acquireRemote2RemoteStub( remote_Interface *pThis ) +{ + Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis; + if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) ) + { + p->m_pEnvRemote->pExtEnv->registerProxyInterface( + p->m_pEnvRemote->pExtEnv, + (void**)&pThis, + freeRemote2RemoteStub, + p->m_sOid.pData, + p->m_pType ); + OSL_ASSERT( (remote_Interface *)p == pThis ); + } +} + +void freeRemote2RemoteStub(uno_ExtEnvironment *, void * stub) { + delete static_cast< Remote2RemoteStub * >(stub); +} + +Remote2RemoteStub::Remote2RemoteStub( rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType, + uno_Environment *pEnvRemote, + requestClientSideDispatcher dispatch ) : + m_sOid( pOid ), + m_pType( (typelib_InterfaceTypeDescription * ) pType ), + m_nRef( 1 ), + m_pEnvRemote( pEnvRemote ), + m_dispatch( dispatch ), + m_nReleaseRemote( 1 ) +{ + typelib_typedescription_acquire( ( typelib_TypeDescription * ) m_pType ); + m_pEnvRemote->acquire( m_pEnvRemote ); + + acquire = acquireRemote2RemoteStub; + release = thisRelease; + pDispatcher = thisDispatch; +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + +Remote2RemoteStub::~Remote2RemoteStub() +{ + + // send a release via the connection ! + sal_Bool bNeedsRelease = sal_False; + if( ! m_pType->aBase.bComplete ) + { + // m_pType may be exchanged during complete, so it needs to be acquired + // (MT : Another thread may use m_pType during e.g. dispatch ! ). + typelib_typedescription_acquire( (typelib_TypeDescription*)m_pType ); + bNeedsRelease = sal_True; + typelib_typedescription_complete( (typelib_TypeDescription **) &m_pType ); + } + + uno_Any any; + uno_Any *pAny = &any; + + typelib_TypeDescription *pReleaseMethod = 0; + typelib_typedescriptionreference_getDescription( + &pReleaseMethod , + m_pType->ppAllMembers[REMOTE_RELEASE_METHOD_INDEX] ); + for( int i = 0 ; i < m_nReleaseRemote ; i ++ ) + { + thisDispatch( this, + pReleaseMethod, + 0, + 0, + &pAny ); + } + typelib_typedescription_release( pReleaseMethod ); + if( bNeedsRelease ) + { + typelib_typedescription_release( (typelib_TypeDescription * ) m_pType ); + } + + typelib_typedescription_release( (typelib_TypeDescription * ) m_pType ); + m_pEnvRemote->release( m_pEnvRemote ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + +void Remote2RemoteStub::releaseRemote() +{ + osl_incrementInterlockedCount( &m_nReleaseRemote ); +} + +} // end namespace bridges_remote diff --git a/bridges/source/remote/static/remote_types.cxx b/bridges/source/remote/static/remote_types.cxx new file mode 100644 index 000000000000..d2c8b17516de --- /dev/null +++ b/bridges/source/remote/static/remote_types.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: remote_types.cxx,v $ + * $Revision: 1.5 $ + * + * 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 "remote_types.hxx" + +namespace bridges_remote { + +sal_Bool SAL_CALL remote_relatesToInterface2( typelib_TypeDescription * pTypeDescr ) +{ + switch (pTypeDescr->eTypeClass) + { + case typelib_TypeClass_SEQUENCE: + { + switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass) + { + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); + sal_Bool bRel = remote_relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + return bRel; + } + default: + break; + } + } + 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 sal_True; + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, pTypes[nPos] ); + sal_Bool bRel = remote_relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + if (bRel) + return sal_True; + break; + } + default: + break; + } + } + if (pComp->pBaseTypeDescription) + return remote_relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription ); + break; + } + default: + OSL_ASSERT( 0 ); + } + return sal_False; +} + +} diff --git a/bridges/source/remote/static/remote_types.hxx b/bridges/source/remote/static/remote_types.hxx new file mode 100644 index 000000000000..b6276f51a55a --- /dev/null +++ b/bridges/source/remote/static/remote_types.hxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: remote_types.hxx,v $ + * $Revision: 1.4 $ + * + * 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_REMOTE_TYPES_HXX_ +#define _BRIDGES_REMOTE_TYPES_HXX_ + +#include <osl/diagnose.h> +#include <sal/types.h> +#include <typelib/typedescription.h> + +namespace bridges_remote +{ + +inline sal_Bool SAL_CALL remote_relatesToInterface( typelib_TypeDescription *pTypeDescr ); +sal_Bool SAL_CALL remote_relatesToInterface2( typelib_TypeDescription * pTypeDescr ); + + +/** 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 sal_Bool SAL_CALL remote_relatesToInterface( typelib_TypeDescription * pTypeDescr ) +{ + switch (pTypeDescr->eTypeClass) + { + 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 sal_True; + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + return remote_relatesToInterface2( pTypeDescr ); + default: + return sal_False; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + return remote_relatesToInterface2( pTypeDescr ); + case typelib_TypeClass_UNION: // might relate to interface + case typelib_TypeClass_ANY: // might relate to interface + case typelib_TypeClass_INTERFACE: + return sal_True; + default: + return sal_False; + } +} + +/** 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 sal_Bool SAL_CALL remote_isSimpleType( typelib_TypeDescription * pTypeDescr ) +{ + return (pTypeDescr->eTypeClass <= typelib_TypeClass_ENUM && + pTypeDescr->eTypeClass != typelib_TypeClass_STRING && + pTypeDescr->eTypeClass != typelib_TypeClass_ANY && + pTypeDescr->eTypeClass != typelib_TypeClass_TYPE); +} + +} +#endif diff --git a/bridges/source/remote/static/stub.cxx b/bridges/source/remote/static/stub.cxx new file mode 100644 index 000000000000..471d564fc219 --- /dev/null +++ b/bridges/source/remote/static/stub.cxx @@ -0,0 +1,339 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: stub.cxx,v $ + * $Revision: 1.11 $ + * + * 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 <osl/diagnose.h> + +#include <uno/data.h> +#include <uno/mapping.hxx> + +#include <bridges/remote/stub.hxx> +#include <bridges/remote/proxy.hxx> +#include <bridges/remote/context.h> +#include <bridges/remote/bridgeimpl.hxx> + +#include "remote_types.hxx" + +#if OSL_DEBUG_LEVEL > 1 +#include <bridges/remote/counter.hxx> +static MyCounter thisCounter( "DEBUG : Uno2RemoteStub"); +#endif + +using namespace ::com::sun::star::uno; +using namespace bridges_remote; + +extern "C" { + +void SAL_CALL thisRelease( remote_Interface *pThis ) +{ + Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis; + if (! osl_decrementInterlockedCount( &(p->m_nRef) )) + { + p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis ); + } +} + +void SAL_CALL thisDispatch( + remote_Interface * pRemoteI, + typelib_TypeDescription const * pType, + void * pReturn, + void * ppArgs[], + uno_Any ** ppException ) +{ + Uno2RemoteStub *p = ( Uno2RemoteStub * ) pRemoteI; + + RemoteThreadCounter counter( p->m_pEnvRemote ); + + typelib_InterfaceMethodTypeDescription *pMethodType = 0; + typelib_InterfaceAttributeTypeDescription *pAttributeType = 0; + typelib_TypeDescription *pReturnType = 0; + typelib_TypeDescription **ppArgType = 0; + sal_Int32 nArgCount = 0; + sal_Bool *pbIsIn = 0; + sal_Bool *pbIsOut = 0; + sal_Bool bConversionNeededForReturn = sal_False; + sal_Bool *pbConversionNeeded = 0; + + sal_Int32 i; + //-------------------------------- + // Collect all needed types ! + //-------------------------------- + if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pType->eTypeClass ) + { + pAttributeType = ( typelib_InterfaceAttributeTypeDescription * ) pType; + if( pReturn ) + { + TYPELIB_DANGER_GET( &pReturnType , pAttributeType->pAttributeTypeRef ); + bConversionNeededForReturn = remote_relatesToInterface( pReturnType ); + } + else + { + nArgCount = 1; + ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) ); + pbIsIn = ( sal_Bool * ) alloca( sizeof( sal_Bool ) ); + pbIsOut = ( sal_Bool * ) alloca( sizeof( sal_Bool ) ); + pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) ); + pbIsIn[0] = sal_True; + pbIsOut[0] = sal_False; + ppArgType[0] = 0; + TYPELIB_DANGER_GET( &( ppArgType[0] ) , pAttributeType->pAttributeTypeRef ); + pbConversionNeeded[0] = remote_relatesToInterface( ppArgType[0] ); + } + } + if( typelib_TypeClass_INTERFACE_METHOD == pType->eTypeClass ) + { + pMethodType = ( typelib_InterfaceMethodTypeDescription * ) pType; + TYPELIB_DANGER_GET( &pReturnType , pMethodType->pReturnTypeRef ); + bConversionNeededForReturn = remote_relatesToInterface( pReturnType ); + nArgCount = pMethodType->nParams; + ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) * nArgCount ); + pbIsIn = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount ); + pbIsOut = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount ); + pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount ); + + for( i = 0 ; i < nArgCount ; i ++ ) + { + ppArgType[i] = 0; + TYPELIB_DANGER_GET( & (ppArgType[i]) , pMethodType->pParams[i].pTypeRef ); + pbIsIn[i] = pMethodType->pParams[i].bIn; + pbIsOut[i] = pMethodType->pParams[i].bOut; + pbConversionNeeded[i] = remote_relatesToInterface( ppArgType[i] ); + } + } + + // create Mapping + + void *pUnoReturn = 0; + void **ppUnoArgs = 0; + + if( pReturnType ) + { + if( bConversionNeededForReturn ) + { + pUnoReturn = alloca( pReturnType->nSize ); + } + else + { + pUnoReturn = pReturn; + } + } + + ppUnoArgs = (void **) alloca( nArgCount * sizeof( void * ) ); + for( i = 0 ; i < nArgCount ; i ++ ) + { + if( pbConversionNeeded[i] ) + { + ppUnoArgs[i] = alloca( ppArgType[i]->nSize ); + if( pbIsIn[i] ) + { + uno_copyAndConvertData( + ppUnoArgs[i], + ppArgs[i], + ppArgType[i], + p->m_mapRemote2Uno.get() + ); + } + } + else + { + ppUnoArgs[i] = ppArgs[i]; + } + } + + // do the call + uno_Any any; + uno_Any *pAny = &any; + + p->m_pUnoI->pDispatcher( p->m_pUnoI, + pType, + pUnoReturn, + ppUnoArgs, + &pAny); + + if( ! pAny ) + { + // ------------------ + // No Exception + // ------------------ + + // Map return value + if( pReturnType && bConversionNeededForReturn ) + { + uno_copyAndConvertData( + pReturn , + pUnoReturn, + pReturnType, + p->m_mapUno2Remote.get() ); + uno_destructData( pUnoReturn , pReturnType, 0 ); + } + + // map arguments + for( i = 0 ; i < nArgCount ; i ++ ) + { + if( pbConversionNeeded[i] ) + { + if( pbIsIn[i] ) { + if( pbIsOut[i] ) { + uno_destructData( + ppArgs[i] , + ppArgType[i] , + remote_release ); + uno_copyAndConvertData( ppArgs[i] , + ppUnoArgs[i], + ppArgType[i], + p->m_mapUno2Remote.get() ); + } + } + else // pure out + { + uno_copyAndConvertData( ppArgs[i] , + ppUnoArgs[i], + ppArgType[i], + p->m_mapUno2Remote.get() ); + } + uno_destructData( ppUnoArgs[i], + ppArgType[i], + 0 ); + } + } + *ppException = 0; + } + else + { + // ----------------------- + // an exception occured + // ----------------------- + typelib_TypeDescription *pAnyType = 0; + getCppuType( (Any*) 0 ).getDescription( &pAnyType ); + uno_copyAndConvertData( *ppException , + pAny , + pAnyType, + p->m_mapUno2Remote.get() ); + uno_destructData( pAny , pAnyType , 0 ); + typelib_typedescription_release( pAnyType ); + + // destruct uno in parameters ( out parameters have not been constructed ) + for( i = 0 ; i < nArgCount ; i ++ ) + { + if( pbConversionNeeded[i] && pbIsIn[i] ) + { + uno_destructData( ppUnoArgs[i], + ppArgType[i], + 0 ); + } + } + } + + //-------------------------- + // release all acquired types + //-------------------------- + if( pReturnType ) + { + TYPELIB_DANGER_RELEASE( pReturnType ); + } + for( i = 0 ; i < nArgCount ; i ++ ) + { + TYPELIB_DANGER_RELEASE( ppArgType[ i] ); + } +} + +} + +namespace bridges_remote { + +void acquireUno2RemoteStub( remote_Interface *pThis ) +{ + Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis; + if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) ) + { + + p->m_pEnvRemote->pExtEnv->registerProxyInterface( + p->m_pEnvRemote->pExtEnv, + (void**)&pThis, + freeUno2RemoteStub, + p->m_sOid.pData, + p->m_pType ); + + OSL_ASSERT( (remote_Interface*) p == pThis ); + } +} + +void freeUno2RemoteStub(uno_ExtEnvironment *, void * stub) { + delete static_cast< Uno2RemoteStub * >(stub); +} + +Uno2RemoteStub::Uno2RemoteStub( uno_Interface *pUnoI, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pType, + uno_Environment *pEnvUno, + uno_Environment *pEnvRemote ) : + m_sOid( pOid ), + m_pType( pType ), + m_pUnoI( pUnoI ), + m_nRef( 1 ), + m_pEnvUno( pEnvUno ), + m_pEnvRemote( pEnvRemote ), + m_mapRemote2Uno( pEnvRemote, pEnvUno ), + m_mapUno2Remote( pEnvUno, pEnvRemote ) +{ + typelib_typedescription_acquire( (typelib_TypeDescription * )m_pType ); + m_pEnvUno->acquire( m_pEnvUno ); + m_pEnvRemote->acquire( m_pEnvRemote ); + + acquire = acquireUno2RemoteStub; + release = thisRelease; + pDispatcher = thisDispatch; + + m_pEnvUno->pExtEnv->registerInterface( m_pEnvUno->pExtEnv, + (void **)&m_pUnoI, + m_sOid.pData, + m_pType ); + m_pUnoI->acquire( m_pUnoI ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + +Uno2RemoteStub::~Uno2RemoteStub() +{ + m_pEnvUno->pExtEnv->revokeInterface( m_pEnvUno->pExtEnv , m_pUnoI ); + + typelib_typedescription_release( (typelib_TypeDescription * )m_pType ); + m_pUnoI->release( m_pUnoI ); + m_pEnvUno->release( m_pEnvUno ); + m_pEnvRemote->release( m_pEnvRemote ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + +} // end namespace bridges_remote diff --git a/bridges/source/remote/urp/makefile.mk b/bridges/source/remote/urp/makefile.mk new file mode 100644 index 000000000000..ca550f3a1a3b --- /dev/null +++ b/bridges/source/remote/urp/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.21 $ +# +# 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=urp_uno +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/urp_environment.obj \ + $(SLO)$/urp_marshal.obj \ + $(SLO)$/urp_unmarshal.obj \ + $(SLO)$/urp_dispatch.obj \ + $(SLO)$/urp_job.obj \ + $(SLO)$/urp_reader.obj \ + $(SLO)$/urp_writer.obj \ + $(SLO)$/urp_log.obj \ + $(SLO)$/urp_bridgeimpl.obj \ + $(SLO)$/urp_propertyobject.obj \ + $(SLO)$/urp_threadid.obj + +.IF "$(COM)"=="GCC" +NOOPTFILES= \ + $(SLO)$/urp_reader.obj +.ENDIF # "$(COM)"=="GCC" + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1STDLIBS=\ + $(SALLIB)\ + $(CPPULIB) + +SHL1LIBS=\ + $(SLB)$/$(TARGET).lib \ + $(SLB)$/bridges_remote_static.lib + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/bridges/source/remote/urp/urp_bridgeimpl.cxx b/bridges/source/remote/urp/urp_bridgeimpl.cxx new file mode 100644 index 000000000000..7ff2f6874861 --- /dev/null +++ b/bridges/source/remote/urp/urp_bridgeimpl.cxx @@ -0,0 +1,253 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_bridgeimpl.cxx,v $ + * $Revision: 1.13 $ + * + * 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/thread.h> +#include <bridges/remote/helper.hxx> + +#include <algorithm> + +#include "urp_bridgeimpl.hxx" + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; +namespace bridges_urp +{ + +template < class t > +inline t mymin( const t & val1, const t & val2 ) +{ + return val1 < val2 ? val1 : val2; +} + +/*********** + * urp_BridgeImpl + ***********/ +urp_BridgeImpl::urp_BridgeImpl( sal_Int32 nCacheSize , sal_uInt32 nInitialMarshalerSize ) : + m_blockMarshaler( this , nInitialMarshalerSize , ::bridges_remote::remote_retrieveOidFromProxy), + m_nMarshaledMessages( 0 ), + m_oidCacheOut( (sal_uInt16)nCacheSize ), + m_tidCacheOut( (sal_uInt16)nCacheSize ), + m_typeCacheOut( (sal_uInt16)nCacheSize ) +{ + m_pOidIn = new OUString[ nCacheSize ]; + m_pTidIn = new ByteSequence[ nCacheSize ]; + m_pTypeIn = new Type[ nCacheSize ]; + m_nRemoteThreads = 0; +} + +urp_BridgeImpl::~urp_BridgeImpl() +{ + delete [] m_pOidIn; + delete [] m_pTidIn; + delete [] m_pTypeIn; +} + + +void urp_BridgeImpl::applyProtocolChanges( const Properties &props ) +{ + if( m_properties.nTypeCacheSize != props.nTypeCacheSize ) + { + if( props.nTypeCacheSize == 0 ) + { + delete [] m_pTypeIn; + m_pTypeIn = 0; + } + else + { + Type *pNew = new Type[props.nTypeCacheSize]; + sal_Int32 i; + sal_Int32 iMin = mymin( m_properties.nTypeCacheSize , props.nTypeCacheSize ); + for( i = 0; i < iMin ; i ++ ) + { + pNew[i] = m_pTypeIn[i]; + } + delete [] m_pTypeIn; + m_pTypeIn = pNew; + } + OSL_ASSERT( props.nTypeCacheSize <= 0xffff ); + m_properties.nTypeCacheSize = props.nTypeCacheSize; + m_typeCacheOut.resize( (sal_uInt16)props.nTypeCacheSize ); + } + + if( m_properties.nOidCacheSize != props.nOidCacheSize ) + { + if( 0 == props.nOidCacheSize ) + { + delete [] m_pOidIn; + m_pOidIn = 0; + } + else + { + OUString *pNew = new OUString[props.nOidCacheSize]; + sal_Int32 i; + sal_Int32 iMin = mymin( m_properties.nOidCacheSize , props.nOidCacheSize ); + for( i = 0; i < iMin ; i ++ ) + { + pNew[i] = m_pOidIn[i]; + } + delete [] m_pOidIn; + m_pOidIn = pNew; + } + OSL_ASSERT( props.nOidCacheSize <= 0xffff ); + m_oidCacheOut.resize( (sal_uInt16)props.nOidCacheSize ); + m_properties.nOidCacheSize = props.nOidCacheSize; + } + + if( m_properties.nTidCacheSize != props.nTidCacheSize ) + { + if( 0 == props.nTidCacheSize ) + { + delete [] m_pTidIn; + m_pTidIn = 0; + } + else + { + ByteSequence *pNew = new ByteSequence[props.nTidCacheSize]; + sal_Int32 i; + sal_Int32 iMin = mymin( m_properties.nTidCacheSize , props.nTidCacheSize ); + for( i = 0; i < iMin ; i ++ ) + { + pNew[i] = m_pTidIn[i]; + } + delete [] m_pTidIn; + m_pTidIn = pNew; + } + OSL_ASSERT( props.nTidCacheSize <= 0xffff ); + m_tidCacheOut.resize( (sal_uInt16)props.nTidCacheSize ); + m_properties.nTidCacheSize = props.nTidCacheSize; + } + + if( m_properties.sVersion != props.sVersion ) + { + m_properties.sVersion = props.sVersion; + } + + if( m_properties.nFlushBlockSize != props.nFlushBlockSize ) + { + m_properties.nFlushBlockSize = props.nFlushBlockSize; + } + + if( m_properties.nOnewayTimeoutMUSEC != props.nOnewayTimeoutMUSEC ) + { + m_properties.nOnewayTimeoutMUSEC = props.nOnewayTimeoutMUSEC; + } + + if( props.bClearCache ) + { + if( m_properties.nTypeCacheSize ) + { + delete [] m_pTypeIn; + m_pTypeIn = new Type[m_properties.nTypeCacheSize]; + m_typeCacheOut.clear(); + } + m_lastInType = Type(); + m_lastOutType = Type(); + + if( m_properties.nOidCacheSize ) + { + delete [] m_pOidIn; + m_pOidIn = new OUString[ m_properties.nOidCacheSize]; + m_oidCacheOut.clear(); + } + m_lastOutOid = OUString(); + m_lastInOid = OUString(); + + if( m_properties.nTidCacheSize ) + { + delete [] m_pTidIn; + m_pTidIn = new ByteSequence[m_properties.nTidCacheSize]; + m_tidCacheOut.clear(); + } + m_lastInTid = ByteSequence(); + m_lastOutTid = ByteSequence(); + } + + if( m_properties.bNegotiate != props.bNegotiate ) + { + m_properties.bNegotiate = props.bNegotiate; + } + + if( m_properties.bForceSynchronous != props.bForceSynchronous ) + { + m_properties.bForceSynchronous = props.bForceSynchronous; + } + + m_properties.bCurrentContext = props.bCurrentContext; +} + +void urp_BridgeImpl::addError( char const *pError ) +{ + OUString message = OUString( RTL_CONSTASCII_USTRINGPARAM( "(tid=" ) ); + message += OUString::valueOf( (sal_Int32 ) osl_getThreadIdentifier( 0 ) ); + message += OUString::createFromAscii( ") " ); + message += OUString::createFromAscii( pError ); + MutexGuard guard( m_errorListMutex ); + m_lstErrors.push_back( message ); +} + +void urp_BridgeImpl::addError( const OUString & error ) +{ + OUString message = OUString( RTL_CONSTASCII_USTRINGPARAM( "(tid=" ) ); + message += OUString::valueOf( (sal_Int32 ) osl_getThreadIdentifier( 0 ) ); + message += OUString::createFromAscii( ") " ); + message += error; + MutexGuard guard( m_errorListMutex ); + m_lstErrors.push_back( message ); +} + +void urp_BridgeImpl::dumpErrors( FILE * f) +{ + MutexGuard guard( m_errorListMutex ); + for( ::std::list< OUString >::iterator ii = m_lstErrors.begin() ; + ii != m_lstErrors.end() ; + ++ii ) + { + OString o = OUStringToOString( *ii , RTL_TEXTENCODING_UTF8 ); + fprintf( f, "%s\n" , o.getStr() ); + } +} + +OUString urp_BridgeImpl::getErrorsAsString( ) +{ + MutexGuard guard( m_errorListMutex ); + OUString ret; + for( ::std::list< OUString >::iterator ii = m_lstErrors.begin() ; + ii != m_lstErrors.end() ; + ++ii ) + { + ret += *ii; + } + return ret; +} + +} diff --git a/bridges/source/remote/urp/urp_bridgeimpl.hxx b/bridges/source/remote/urp/urp_bridgeimpl.hxx new file mode 100644 index 000000000000..d483ee834a5e --- /dev/null +++ b/bridges/source/remote/urp/urp_bridgeimpl.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_bridgeimpl.hxx,v $ + * $Revision: 1.10 $ + * + * 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 _URP_BRIDGEIMPL_HXX_ +#define _URP_BRIDGEIMPL_HXX_ + +#include <stdio.h> +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <rtl/ustring.hxx> +#include <rtl/byteseq.hxx> + +#ifndef _UNO_THREADPOOL_H_ +#include <uno/threadpool.h> +#endif +#include <bridges/remote/bridgeimpl.hxx> + +#ifndef _URP_CACHE_HXX_ +#include "urp_cache.hxx" +#endif +#include "urp_marshal_decl.hxx" + +#ifndef _URP_REPLYCONTAINER_HXX_ +#include "urp_replycontainer.hxx" +#endif +#include "urp_property.hxx" + + +namespace bridges_urp +{ + +class PropertyObject; + +struct equalOUString +{ + sal_Int32 operator() ( const ::rtl::OUString &s1, const ::rtl::OUString &s2 ) const + { + return s1 == s2; + } +}; + +struct equalType +{ + sal_Int32 operator() ( const ::com::sun::star::uno::Type &t1, + const ::com::sun::star::uno::Type &t2 ) const + { + return t1 == t2; + } +}; + +class OWriterThread; +class OReaderThread; + +struct urp_BridgeImpl : + public remote_BridgeImpl +{ + urp_BridgeImpl( sal_Int32 nCacheSize , sal_uInt32 nInitialMarshalerSize ); + ~urp_BridgeImpl(); + + void applyProtocolChanges( const Properties & ); + + void startBlockBridge(); + void stopBlockBridge(); + void addError( char const *pError ); + void addError( const ::rtl::OUString &anError ); + void dumpErrors( FILE *f ); + ::rtl::OUString getErrorsAsString(); + + ::osl::Mutex m_marshalingMutex; + ::osl::Mutex m_disposingMutex; + ::osl::Mutex m_errorListMutex; + Marshal m_blockMarshaler; + sal_Int32 m_nMarshaledMessages; + + // Caches for vars, that go from local process to the remote process + Cache < ::rtl::OUString , equalOUString > m_oidCacheOut; + Cache < ::rtl::ByteSequence , EqualThreadId > m_tidCacheOut; + Cache < ::com::sun::star::uno::Type , equalType > m_typeCacheOut; + + ::com::sun::star::uno::Type m_lastOutType; + ::rtl::ByteSequence m_lastOutTid; + ::rtl::OUString m_lastOutOid; + + // Caches for vars, that come from the remote process to the local process + ::rtl::OUString *m_pOidIn; + ::rtl::ByteSequence *m_pTidIn; + ::com::sun::star::uno::Type *m_pTypeIn; + + ::com::sun::star::uno::Type m_lastInType; + ::rtl::ByteSequence m_lastInTid; + ::rtl::OUString m_lastInOid; + + urp_ClientJobContainer m_clientJobContainer; + + OWriterThread *m_pWriter; + OReaderThread *m_pReader; + ::rtl::OString m_sLogFileName; + FILE *m_pLogFile; + ::osl::Condition m_initialized; + ::osl::Condition m_cndWaitForThreads; + + struct Properties m_properties; + class PropertyObject *m_pPropertyObject; + ::std::list< ::rtl::OUString > m_lstErrors; + uno_ThreadPool m_hThreadPool; +}; + + +} +#endif diff --git a/bridges/source/remote/urp/urp_cache.h b/bridges/source/remote/urp/urp_cache.h new file mode 100644 index 000000000000..ea77a77843ca --- /dev/null +++ b/bridges/source/remote/urp/urp_cache.h @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_cache.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + + +namespace bridges_urp +{ + template < class t , class tequals > + class Cache + { + public: + inline Cache ( sal_uInt16 nMaxEntries ); + inline ~Cache(); + + // puts the value t into the cache. Returns then entry, + // that is used for this value. + inline sal_uInt16 put( const t & ); + + // lookup, if there is an entry for this value + // returns 0xffff, when value cannot be found in the list + inline sal_uInt16 seek( const t & ); + + // resizes the cache, conserving overlapping values + inline void resize( sal_uInt16 nNewMaxEntries ); + + // empties the cache + inline void clear(); + private: + t *m_pCache; + ::std::list< sal_uInt16 > m_lstLeastRecentlyUsed; + sal_uInt16 m_nMaxEntries; + sal_uInt16 m_nEntries; + }; +} diff --git a/bridges/source/remote/urp/urp_cache.hxx b/bridges/source/remote/urp/urp_cache.hxx new file mode 100644 index 000000000000..5702fb387dc5 --- /dev/null +++ b/bridges/source/remote/urp/urp_cache.hxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_cache.hxx,v $ + * $Revision: 1.7 $ + * + * 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 <list> +#include <algorithm> +#include <rtl/ustring.hxx> + +#include "urp_threadid.hxx" +#include "urp_cache.h" + +namespace bridges_urp +{ + + template < class t , class tequals > + inline Cache< t , tequals >::Cache( sal_uInt16 nMaxEntries ) : + m_pCache( new t[nMaxEntries] ), + m_nMaxEntries( nMaxEntries ), + m_nEntries( 0 ) + { + + } + + template < class t , class tequals > + inline Cache< t , tequals >::~Cache( ) + { + delete [] m_pCache; + } + + + template < class t , class tequals > + inline sal_uInt16 Cache< t , tequals >::put( const t & value ) + { + if( ! m_nMaxEntries ) + { + return 0xffff; + } + sal_uInt16 nEntry = 0xffff; + if( m_nEntries < m_nMaxEntries ) + { + // cache has still empty places + m_pCache[m_nEntries] = value; + nEntry = m_nEntries; + m_nEntries ++; + + // add it to the cache + m_lstLeastRecentlyUsed.push_front( nEntry ); + } + else + { + // cache is full, remove an element and insert the new one + nEntry = m_lstLeastRecentlyUsed.back(); + m_lstLeastRecentlyUsed.pop_back(); + m_lstLeastRecentlyUsed.push_front( nEntry ); + + m_pCache[nEntry] = value; + } + return nEntry; + } + + template < class t , class tequals > + inline sal_uInt16 Cache< t , tequals >::seek( const t & value ) + { + for( ::std::list< sal_uInt16 >::iterator ii = m_lstLeastRecentlyUsed.begin() ; + ii != m_lstLeastRecentlyUsed.end() ; + ++ ii ) + { + if( value == m_pCache[*ii] ) + { + sal_uInt16 nEntry = *ii; + m_lstLeastRecentlyUsed.erase( ii ); + m_lstLeastRecentlyUsed.push_front( nEntry ); + return nEntry; + } + } + return 0xffff; + } + + // helper predicate for element removal + template < class t > + struct PredicateOverMax + { + t m_; + inline PredicateOverMax( const t &value ) : m_(value) + {} + sal_Int32 operator () ( const t &value ) const + { return value >= m_; } + }; + + template < class t, class tequals > + inline void Cache < t , tequals >::resize( sal_uInt16 nNewMaxEntries ) + { + if( 0 == nNewMaxEntries ) + { + m_lstLeastRecentlyUsed.clear(); + delete [] m_pCache; + m_pCache = 0; + m_nMaxEntries = 0; + } + else + { + // allocate + t *pNew = new t[nNewMaxEntries]; + sal_Int32 nMin = nNewMaxEntries < m_nMaxEntries ? nNewMaxEntries : m_nMaxEntries; + + // copy + for( sal_Int32 i = 0; i < nMin ; i ++ ) + { + pNew[i] = m_pCache[i]; + } + // delete + delete [] m_pCache; + + // assign + m_pCache = pNew; + + // remove overlapping lru cache entries + ::std::remove_if(m_lstLeastRecentlyUsed.begin(), + m_lstLeastRecentlyUsed.end(), + PredicateOverMax< sal_Int32 > ( nMin ) ); + } + m_nMaxEntries = nNewMaxEntries; + m_nEntries = m_nEntries < m_nMaxEntries ? + m_nEntries : m_nMaxEntries; + } + + template < class t, class tequals > + inline void Cache < t, tequals >:: clear() + { + for( sal_Int32 i = 0; i < m_nMaxEntries ; i ++ ) + { + m_pCache[i] = t(); + } + m_lstLeastRecentlyUsed.clear(); + m_nEntries = 0; + } +} diff --git a/bridges/source/remote/urp/urp_dispatch.cxx b/bridges/source/remote/urp/urp_dispatch.cxx new file mode 100644 index 000000000000..c5ba6a93140d --- /dev/null +++ b/bridges/source/remote/urp/urp_dispatch.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_dispatch.cxx,v $ + * $Revision: 1.17.20.1 $ + * + * 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 <osl/mutex.hxx> +#include <osl/diagnose.h> + +#include <rtl/alloc.h> +#include <rtl/ustrbuf.hxx> + +#include <uno/mapping.hxx> +#include <uno/threadpool.h> + +#include <bridges/remote/remote.h> +#include <bridges/remote/stub.hxx> +#include <bridges/remote/proxy.hxx> +#include <bridges/remote/remote.hxx> + +#include "urp_bridgeimpl.hxx" +#include "urp_marshal.hxx" +#include "urp_dispatch.hxx" +#include "urp_job.hxx" +#include "urp_writer.hxx" +#include "urp_log.hxx" + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; + +namespace bridges_urp +{ + +void SAL_CALL urp_sendCloseConnection( uno_Environment *pEnvRemote ) +{ + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl ); + + { + MutexGuard guard( pImpl->m_marshalingMutex ); + + // send immediately + if( ! pImpl->m_blockMarshaler.empty() ) + { + pImpl->m_pWriter->touch( sal_True ); + } + + pImpl->m_pWriter->sendEmptyMessage(); + } +} +extern "C" void SAL_CALL urp_sendRequest( + uno_Environment *pEnvRemote, + typelib_TypeDescription const * pMemberType, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException ) +{ + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl ); + pImpl->m_initialized.wait(); + urp_sendRequest_internal( + pEnvRemote, pMemberType, pOid, pInterfaceType, pReturn, ppArgs, + ppException ); +} +void SAL_CALL urp_sendRequest_internal( + uno_Environment *pEnvRemote, + typelib_TypeDescription const * pMemberType, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException ) +{ + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl ); + + ClientJob job( + pEnvRemote, pContext, pImpl, pOid, pMemberType, pInterfaceType, pReturn, + ppArgs, ppException); + + if( job.pack() && ! job.isOneway() ) + { + job.wait(); + } +} + +} + + diff --git a/bridges/source/remote/urp/urp_dispatch.hxx b/bridges/source/remote/urp/urp_dispatch.hxx new file mode 100644 index 000000000000..dd529f97bffb --- /dev/null +++ b/bridges/source/remote/urp/urp_dispatch.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_dispatch.hxx,v $ + * $Revision: 1.6 $ + * + * 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 <rtl/ustring.hxx> + +#include <typelib/typedescription.h> + +#include <uno/any2.h> + + +typedef struct _uno_Environment uno_Environment; +struct remote_Interface; + + + +namespace bridges_urp { + + const sal_uInt8 HDRFLAG_LONGHEADER = 0x80; + const sal_uInt8 HDRFLAG_REQUEST = 0x40; + const sal_uInt8 HDRFLAG_NEWTYPE = 0x20; + const sal_uInt8 HDRFLAG_NEWOID = 0x10; + const sal_uInt8 HDRFLAG_NEWTID = 0x08; + const sal_uInt8 HDRFLAG_LONGMETHODID = 0x04; + const sal_uInt8 HDRFLAG_IGNORECACHE = 0x02; + const sal_uInt8 HDRFLAG_MOREFLAGS = 0x01; + const sal_uInt8 HDRFLAG_MUSTREPLY = 0x80; + const sal_uInt8 HDRFLAG_SYNCHRONOUS = 0x40; + + const sal_uInt8 HDRFLAG_EXCEPTION = 0x20; + + void SAL_CALL urp_sendCloseConnection( uno_Environment *pEnvRemote ); + + extern "C" void SAL_CALL urp_sendRequest( + uno_Environment *pEnvRemote, + typelib_TypeDescription const * pMemberType, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException + ); + + void SAL_CALL urp_sendRequest_internal( + uno_Environment *pEnvRemote, + typelib_TypeDescription const * pMemberType, + rtl_uString *pOid, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException + ); + +} + diff --git a/bridges/source/remote/urp/urp_environment.cxx b/bridges/source/remote/urp/urp_environment.cxx new file mode 100644 index 000000000000..1afab0633fd4 --- /dev/null +++ b/bridges/source/remote/urp/urp_environment.cxx @@ -0,0 +1,554 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_environment.cxx,v $ + * $Revision: 1.21.20.2 $ + * + * 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 <osl/interlck.h> +#include <osl/diagnose.h> +#include <osl/conditn.h> +#include <osl/mutex.hxx> +#include <osl/process.h> + +#include <rtl/alloc.h> +#include <rtl/uuid.h> +#include <rtl/unload.h> + +#include <uno/environment.h> +#include <uno/lbnames.h> +#include <uno/mapping.hxx> +#include <uno/threadpool.h> + +#include <com/sun/star/uno/Sequence.hxx> + +#include <bridges/remote/proxy.hxx> +#include <bridges/remote/stub.hxx> +#include <bridges/remote/context.h> +#include <bridges/remote/mapping.hxx> +#include <bridges/remote/counter.hxx> +#include <bridges/remote/bridgeimpl.hxx> +#include <bridges/remote/helper.hxx> + +#include "urp_bridgeimpl.hxx" +#include "urp_writer.hxx" +#include "urp_reader.hxx" +#include "urp_dispatch.hxx" +#include "urp_log.hxx" +#include "urp_propertyobject.hxx" + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; + +namespace bridges_urp +{ +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +// static void dumpProperties( struct Properties *p ) +// { +// fprintf( stderr , "FlushBlockSize : %d\n" , p->nFlushBlockSize ); +// fprintf( stderr , "OnewayTimeoutMUSEC : %d\n" , p->nOnewayTimeoutMUSEC ); +// fprintf( stderr , "OidCacheSize : %d\n" , p->nOidCacheSize ); +// fprintf( stderr , "TypeCacheSize : %d\n" , p->nTypeCacheSize ); +// fprintf( stderr , "TidCacheSize : %d\n" , p->nTidCacheSize ); +// OString o = OUStringToOString( p->sSupportedVersions , RTL_TEXTENCODING_ASCII_US ); +// fprintf( stderr , "SupportedVersions : %s\n" , o.pData->buffer ); +// o = OUStringToOString( p->sVersion , RTL_TEXTENCODING_ASCII_US ); +// fprintf( stderr , "Version : %s\n" , o.pData->buffer ); +// fprintf( stderr , "SupportsMultipleSynchronous : %d\n" , p->bSupportsMultipleSynchronous ); +// fprintf( stderr , "SupportsMustReply : %d\n" , p->bSupportsMustReply ); +// fprintf( stderr , "SupportsSynchronous : %d\n" , p->bSupportsSynchronous ); +// } + +// PropertySetterThread +//------------------------------------ +class PropertySetterThread : public ::osl::Thread +{ + urp_BridgeImpl *m_pImpl; + ::rtl::OUString m_sProps; + uno_Environment *m_pEnvRemote; +public: + PropertySetterThread( uno_Environment *pEnvRemote, + urp_BridgeImpl *pImpl, + const ::rtl::OUString & props ) + : m_pImpl( pImpl ) + , m_sProps( props ) + , m_pEnvRemote( pEnvRemote ) + { + if (m_sProps.getLength() > 0) { + m_sProps += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); + } + m_sProps += rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("CurrentContext=")); + // hold the environment in case all references are released before this + // thread terminates + m_pEnvRemote->acquire( pEnvRemote ); + } + ~PropertySetterThread() + { + m_pEnvRemote->release( m_pEnvRemote ); + } + + virtual void SAL_CALL run() + { + for (;;) + { + switch ( m_pImpl->m_pPropertyObject->localRequestChange( ) ) + { + case 1: + sal_Bool bExceptionThrown; + m_pImpl->m_pPropertyObject->localCommitChange( m_sProps , &bExceptionThrown ); + OSL_ENSURE( !bExceptionThrown, "properties were not set\n" ); + goto done; + case 0: + OSL_TRACE( "urp-bridge : remote-counterpart won the changing-the-protocol-race\n" ); + goto done; + } + } + done: + m_pImpl->m_initialized.set(); + } + virtual void SAL_CALL onTerminated() + { + delete this; + } +}; +//------------------------------------ + + +void test_cache() +{ + OUString a = OUString( RTL_CONSTASCII_USTRINGPARAM( "a" ) ); + OUString b = OUString( RTL_CONSTASCII_USTRINGPARAM( "b" ) ); + OUString c = OUString( RTL_CONSTASCII_USTRINGPARAM( "c" ) ); + Cache < OUString , equalOUString > cache ( 2 ); + + sal_Int32 n = cache.put( a ); + if (cache.seek( a ) != n) + { + OSL_ASSERT( false ); + } + OSL_ASSERT( 0 == n ); + + n = cache.put( b ); + OSL_ASSERT( 1 == n ); + + cache.put( c ); + + OSL_ASSERT( 0xffff == cache.seek( a ) ); + OSL_ASSERT( 1 == cache.seek( b ) ); + OSL_ASSERT( 0 == cache.seek( c ) ); + + OSL_ASSERT( 1 == cache.put( a ) ); + OSL_ASSERT( 0xffff == cache.seek( b) ); + OSL_ASSERT( 1 == cache.seek( a ) ); + OSL_ASSERT( 0 == cache.seek( c ) ); +} + +/******************* + * Are we within thread, that calls destructors of static objects ? + *******************/ +sal_Bool g_bStaticDestructorsCalled = sal_False; +struct StaticSingleton +{ + ~StaticSingleton() + { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + g_bStaticDestructorsCalled = sal_True; + } +}; +StaticSingleton singleton; + +#if OSL_DEBUG_LEVEL > 1 +static MyCounter thisCounter( "Remote Environment" ); +#endif + +void SAL_CALL allThreadsAreGone( uno_Environment * pEnvRemote ) +{ + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = ( urp_BridgeImpl *) pContext->m_pBridgeImpl; + + // if the current thread is not the writer thread, the writer thread + // object is not destroyed up to now, though it may already have run out. + // In both cases, it must be safe to cal pImpl->m_pWriter->getIdentifier() + OSL_ASSERT( pImpl->m_pWriter ); + if( pImpl->m_pWriter->getIdentifier() == osl_getThreadIdentifier(0) ) + { + // This is the writer thread. It has done some release calls, + // and is now the last one, that was active. Because the writer + // thread holds the environment weakly, there may also be a thread within + // the dispose of the bridge ( because the enviroment may have a refcount == 0 ). + // However, this thread MUST wait for the writer thread, so it is perfectly ok, + // not to set m_cndWaitForThreads. ( The check for m_nRemoteThreads is done + // after the join of the writer thread ). + } + else + { + pImpl->m_cndWaitForThreads.set(); + } + +} + +void SAL_CALL releaseStubs( uno_Environment *pEnvRemote ) +{ + + ((remote_Context * ) pEnvRemote->pContext )->m_pBridgeImpl->m_bReleaseStubsCalled = sal_True; + + remote_Interface **ppInterfaces = 0; + sal_Int32 nCount; + pEnvRemote->pExtEnv->getRegisteredInterfaces( pEnvRemote->pExtEnv, + (void***)&ppInterfaces, + &nCount, + rtl_allocateMemory ); + + sal_Int32 i; + for( i = 0 ; i < nCount ; i ++ ) + { + if( ppInterfaces[i]->acquire == bridges_remote::acquireUno2RemoteStub ) + { + // these are freed by the environment, so no release necessary + pEnvRemote->pExtEnv->revokeInterface( pEnvRemote->pExtEnv, ppInterfaces[i] ); + } + else + { + ppInterfaces[i]->release( ppInterfaces[i] ); + } + } + + rtl_freeMemory( (void*) ppInterfaces ); +} + +} // end namespace bridges_urp + +using namespace bridges_urp; + +extern "C" { + +static void SAL_CALL RemoteEnvironment_thisDispose( uno_Environment *pEnvRemote ) +{ + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = ( urp_BridgeImpl *) pContext->m_pBridgeImpl; + + ::osl::ClearableMutexGuard guard( pImpl->m_disposingMutex ); + if( pContext->m_pBridgeImpl->m_bDisposed && + ( ! pImpl->m_pReader || + osl_getThreadIdentifier(0) == + (oslThreadIdentifier) pImpl->m_pReader->getIdentifier() ) ) + { + return; + } + // in case, that the static destructors already have been called, no + // tiding up is done. + bool tidyUp; + { + ::osl::MutexGuard guard2( ::osl::Mutex::getGlobalMutex() ); + tidyUp = ! g_bStaticDestructorsCalled && + ! pContext->m_pBridgeImpl->m_bDisposed; + } + if( tidyUp ) + { + // TODO : not threadsafe + // synchronization with dispatch methods needed ! + + pImpl->m_bDisposed = sal_True; + + + // close the connection + uno_threadpool_dispose( pImpl->m_hThreadPool ); + pImpl->m_pWriter->abortThread(); + pContext->m_pConnection->close( pContext->m_pConnection ); + + if( osl_getThreadIdentifier(0) == + (oslThreadIdentifier) pImpl->m_pReader->getIdentifier() ) + { + // This is the reader thread. Let the thread destroy itself + // the reader thread object must also release the connection at this stage ! + pImpl->m_pReader->destroyYourself(); + pImpl->m_pReader = 0; + } + else + { + // wait for the reader thread + // the reader thread object must also release the connection, + // when terminating !!!! + pImpl->m_pReader->join(); + } + + // wait for the writer thread + pImpl->m_pWriter->join(); + + // now let the context go ! + pContext->dispose( pContext ); + + if( 0 != pImpl->m_nRemoteThreads ) + { + // Wait for all threads + guard.clear(); + pImpl->m_cndWaitForThreads.wait(); + OSL_ASSERT( ! pImpl->m_nRemoteThreads ); + } + else + { + guard.clear(); + } +#ifdef BRIDGES_URP_PROT + if( pImpl->m_pLogFile ) + { + fclose( pImpl->m_pLogFile ); + pImpl->m_pLogFile = 0; + } +#endif +#if OSL_DEBUG_LEVEL > 1 + pImpl->dumpErrors( stderr ); +#endif + + // destroy the threads + delete pImpl->m_pWriter; + pImpl->m_pWriter = 0; + + if( pImpl->m_pReader != 0 ) + { + // This is not the reader thread, so the thread object is deleted + delete pImpl->m_pReader; + pImpl->m_pReader = 0; + } + + bool bReleaseStubs = false; + { + ::osl::MutexGuard guard2( ::osl::Mutex::getGlobalMutex() ); + bReleaseStubs = !g_bStaticDestructorsCalled; + } + if( bReleaseStubs ) + { + releaseStubs( pEnvRemote ); + } + } +} + +static void SAL_CALL RemoteEnvironment_thisDisposing( + uno_Environment *pEnvRemote ) +{ + remote_Context *pContext = (remote_Context * )pEnvRemote->pContext; + urp_BridgeImpl *pImpl = ((urp_BridgeImpl*) pContext->m_pBridgeImpl); + + { + ::osl::ClearableMutexGuard guard( pImpl->m_disposingMutex ); + if( ! pImpl->m_bDisposed ) + { + guard.clear(); + urp_sendCloseConnection( pEnvRemote ); + RemoteEnvironment_thisDispose( pEnvRemote ); + } + } + pImpl->m_pPropertyObject->thisRelease(); + pImpl->m_pPropertyObject = 0; + + uno_threadpool_destroy( pImpl->m_hThreadPool ); + + delete pImpl; + pContext->aBase.release( (uno_Context * ) pContext ); + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + +static void SAL_CALL RemoteEnvironment_thisComputeObjectIdentifier( + uno_ExtEnvironment *, rtl_uString **, void *) +{ + OSL_ENSURE( 0, "RemoteEnvironment_thisComputeObjectIdentifier should never be called" ); +} + +static void SAL_CALL RemoteEnvironment_thisAcquireInterface( + uno_ExtEnvironment *, void *pInterface ) +{ + ((remote_Interface *)pInterface)->acquire( ( remote_Interface *) pInterface ); +} + +static void SAL_CALL RemoteEnvironment_thisReleaseInterface( + uno_ExtEnvironment *, void *pInterface ) +{ + ((remote_Interface *)pInterface)->release( ( remote_Interface *) pInterface ); +} + +//################################################################################################## +void SAL_CALL uno_initEnvironment( uno_Environment * pEnvRemote ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + // set C-virtual methods + pEnvRemote->environmentDisposing = RemoteEnvironment_thisDisposing; + pEnvRemote->pExtEnv->computeObjectIdentifier = RemoteEnvironment_thisComputeObjectIdentifier; + pEnvRemote->pExtEnv->acquireInterface = RemoteEnvironment_thisAcquireInterface; + pEnvRemote->pExtEnv->releaseInterface = RemoteEnvironment_thisReleaseInterface; + pEnvRemote->dispose = RemoteEnvironment_thisDispose; + + remote_Context *pContext = ( remote_Context * ) pEnvRemote->pContext; + pContext->aBase.acquire( ( uno_Context * ) pContext ); + pContext->getRemoteInstance = ::bridges_remote::remote_sendQueryInterface; + + // Initialize impl struct urp_BridgeImpl + urp_BridgeImpl *pImpl = new ::bridges_urp::urp_BridgeImpl( 256, 8192 ); + pContext->m_pBridgeImpl = pImpl; + + // Initialize threadpool + pImpl->m_hThreadPool = uno_threadpool_create(); + + // take the bridgepointer as id + pImpl->m_properties.seqBridgeID = ByteSequence( (sal_Int8*)&pEnvRemote , sizeof( pEnvRemote ) ); + + pImpl->m_allThreadsAreGone = allThreadsAreGone; + pImpl->m_sendRequest = urp_sendRequest; + pImpl->m_nRemoteThreads = 0; + pImpl->m_bDisposed = sal_False; + pImpl->m_bReleaseStubsCalled = sal_False; + + pImpl->m_pPropertyObject = new PropertyObject( &(pImpl->m_properties ), pEnvRemote, pImpl ); + pImpl->m_pPropertyObject->thisAcquire(); + + OUString sProtocolProperties; + if( pContext->m_pProtocol->length > 3 ) + { + sProtocolProperties = OUString( pContext->m_pProtocol ).copy( 4, pContext->m_pProtocol->length-4); + } + if( sProtocolProperties.getLength() ) + { + struct Properties props = pImpl->m_properties; + assignFromStringToStruct( sProtocolProperties , &props ); + if( ! props.bNegotiate ) + { + // no negotiation takes place, the creator of the bridge knows the parameter + // of the other side ! + pImpl->applyProtocolChanges( props ); + sProtocolProperties = OUString(); + } + } + +#ifdef BRIDGES_URP_PROT + char *p = getenv( "PROT_REMOTE" ); + pImpl->m_pLogFile = 0; + if( p ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + static int counter; + oslProcessInfo data; + data.Size = sizeof( data ); + osl_getProcessInfo( 0 , osl_Process_HEAPUSAGE | osl_Process_IDENTIFIER , &data ); + OString s(p); + s += "_pid"; + s += OString::valueOf( (sal_Int32) data.Ident ); + s += "_"; + s += OString::valueOf( (sal_Int32) counter ); + pImpl->m_sLogFileName = s; + // clear the file + FILE *f = fopen( s.getStr() , "w" ); + OSL_ASSERT( f ); + if( getenv( "PROT_REMOTE_FAST") ) + { + pImpl->m_pLogFile = f; + } + else + { + fclose( f ); + } + counter++; + } +#endif + + // start reader and writer threads + pImpl->m_pWriter = new ::bridges_urp::OWriterThread( pContext->m_pConnection , pImpl, + pEnvRemote); + pImpl->m_pWriter->create(); + + pImpl->m_pReader = new ::bridges_urp::OReaderThread( pContext->m_pConnection , + pEnvRemote, + pImpl->m_pWriter ); + pImpl->m_pReader->create(); + + PropertySetterThread *pPropsSetterThread = + new PropertySetterThread( pEnvRemote, pImpl , sProtocolProperties ); + pPropsSetterThread->create(); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + + +//################################################################################################## +void SAL_CALL uno_ext_getMapping( + uno_Mapping ** ppMapping, + uno_Environment * pFrom, + uno_Environment * pTo ) +{ + OSL_ASSERT( ppMapping && pFrom && pTo ); + if (ppMapping && pFrom && pTo) + { + if (*ppMapping) + ((*ppMapping)->release)( *ppMapping ); + bridges_remote::RemoteMapping * pMapping = 0; + + ::rtl::OUString sFromName = pFrom->pTypeName; + ::rtl::OUString sToName = pTo->pTypeName; + ::rtl::OUString sUno = OUString::createFromAscii( UNO_LB_UNO ); + ::rtl::OUString sRemote = OUString::createFromAscii( "urp" ); + if ( sFromName.equalsIgnoreAsciiCase( sRemote ) && + sToName.equalsIgnoreAsciiCase( sUno ) ) + { + pMapping = new bridges_remote::RemoteMapping( pTo, /* Uno */ + pFrom, /*remote*/ + bridges_remote::remoteToUno, + OUString() ); + } + else if ( sFromName.equalsIgnoreAsciiCase( sUno ) && + sToName.equalsIgnoreAsciiCase( sRemote ) ) + { + pMapping = new bridges_remote::RemoteMapping( pFrom , + pTo , + bridges_remote::unoToRemote, + OUString() ); + } + + *ppMapping = (uno_Mapping * )pMapping; + OUString dummy; + uno_registerMapping( ppMapping , + bridges_remote::freeRemoteMapping, + pFrom , + pTo , + dummy.pData ); + } +} + +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +} diff --git a/bridges/source/remote/urp/urp_job.cxx b/bridges/source/remote/urp/urp_job.cxx new file mode 100644 index 000000000000..918affdbe689 --- /dev/null +++ b/bridges/source/remote/urp/urp_job.cxx @@ -0,0 +1,942 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_job.cxx,v $ + * $Revision: 1.17 $ + * + * 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 <stdio.h> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> + +#include <rtl/alloc.h> +#include <rtl/ustrbuf.hxx> + +#include <uno/current_context.h> +#include <uno/current_context.hxx> +#include <uno/threadpool.h> + +#include <bridges/cpp_uno/type_misc.hxx> +#include <bridges/remote/proxy.hxx> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +#include "urp_job.hxx" +#include "urp_bridgeimpl.hxx" +#include "urp_writer.hxx" +#include "urp_dispatch.hxx" +#include "urp_log.hxx" +#include "urp_marshal.hxx" +#include "urp_propertyobject.hxx" +#include "urp_reader.hxx" + +using namespace ::std; +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; + +using namespace bridges_urp; + +extern "C" { + +static void SAL_CALL doit(void * job) { + ServerMultiJob * p = static_cast< ServerMultiJob * >(job); + p->execute(); + delete p; +} + +} + +namespace bridges_urp +{ + static sal_Bool isDisposedExceptionDescriptionAvail( const Type &type ) + { + static sal_Bool bInit; + static sal_Bool bReturn; + // we don't care for thread safety here, as both threads must come + // to the same result + if( ! bInit ) + { + typelib_TypeDescription *pTD = 0; + typelib_typedescriptionreference_getDescription( & pTD, type.getTypeLibType() ); + if( pTD ) + { + bReturn = sal_True; + typelib_typedescription_release( pTD ); + } + else + { + bReturn = sal_False; + } + bInit = sal_True; + } + return bReturn; + } + + //-------------------------------------------------------------------------------------- + static void prepareRuntimeExceptionClientSide( uno_Any **ppException , const OUString &s) + { + com::sun::star::lang::DisposedException exception( s , Reference< XInterface > () ); + Type type = ::getCppuType( &exception ); + if( !isDisposedExceptionDescriptionAvail( type ) ) + { + // if it is not available (probably missing type library), + // then we are satisfied with throwing a normal runtime exception, + // for which cppu provides a static description + type = getCppuType( ( RuntimeException * ) 0 ); + } + uno_type_any_construct( *ppException , &exception , type.getTypeLibType() , 0 ); + } + + + Job::Job( uno_Environment *pEnvRemote, + remote_Context *pContext, + sal_Sequence *pTid, + struct urp_BridgeImpl *pBridgeImpl, + Unmarshal *pUnmarshal ) + : m_pContext( pContext ) + , m_pUnmarshal( pUnmarshal ) + , m_pBridgeImpl( pBridgeImpl ) + , m_pTid( pTid ) + , m_counter( pEnvRemote ) + { + if ( m_pContext ) + { + m_pContext->aBase.acquire( &m_pContext->aBase ); + } + if( m_pTid ) + rtl_byte_sequence_acquire( pTid ); + } + + Job::~Job() + { + if( m_pTid ) + rtl_byte_sequence_release( m_pTid ); + if ( m_pContext ) + { + m_pContext->aBase.release( &m_pContext->aBase ); + } + } + + + + + //-------------------------------------------------------------------------------------- + sal_Bool ClientJob::extract( ) + { + sal_Bool bReturn = sal_True; + //------------------------------- + // Handle the reply, unpack data + //------------------------------- + if( m_bExceptionOccured ) + { + bReturn = m_pUnmarshal->unpackAny( *m_ppException ); + } + else + { + //--------------------------------- + // alles ist gut + //--------------------------------- + if( m_pMethodType ) + { + if( m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID ) + { + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType , m_pMethodType->pReturnTypeRef ); + bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn; + TYPELIB_DANGER_RELEASE( pType ); + } + + // out parameters + sal_Int32 i; + for( i = 0 ; i < m_pMethodType->nParams ; i ++ ) + { + if( m_pMethodType->pParams[i].bOut ) + { + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef ); + if( m_pMethodType->pParams[i].bIn ) + { + uno_destructData( m_ppArgs[i] , pType , ::bridges_remote::remote_release ); + } + bReturn = m_pUnmarshal->unpack( m_ppArgs[i] , pType ) && bReturn; + TYPELIB_DANGER_RELEASE( pType ); + } + } + } + else if( m_pAttributeType && m_pReturn ) + { + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef ); + bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn; + TYPELIB_DANGER_RELEASE( pType ); + } + else if( m_pAttributeType && m_ppArgs ) + { + // nothing to do + } + else + { + OSL_ASSERT( 0 ); + } + } + return bReturn; + } + + //------------------------------------------------------------------------------------------- + void ClientJob::initiate() + { + uno_threadpool_putJob( m_pBridgeImpl->m_hThreadPool, m_pTid , this, 0, sal_False); + } + + //-------------------------------------------------------------------------------------------- + sal_Bool ClientJob::pack() + { + sal_Bool bSuccess = sal_True; + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + + if( m_pMethodType && + REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition && + ! m_pBridgeImpl->m_bDisposed && + m_pBridgeImpl->m_pWriter->getIdentifier() != ::osl::Thread::getCurrentIdentifier() ) + { + // all release calls are delegated to the writer thread to avoid + // multiple synchron calls with the same thread id and reentrant + // marshaling (in case during destruction of parameters a release is + // invoked ). + m_pBridgeImpl->m_pWriter->insertReleaseRemoteCall( + m_pOid, m_pInterfaceType->aBase.pWeakRef ); + + // No waiting, please + return sal_False; + } + else if ( m_pMethodType && + REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition && + m_pBridgeImpl->m_bDisposed ) + { + // no exception for release calls ! + return sal_False; + } + else if( m_pBridgeImpl->m_bDisposed ) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP-Bridge: disposed" ) ); + buf.append( m_pBridgeImpl->getErrorsAsString() ); + prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() ); + return sal_False; + } + + // build up the flag byte + sal_Bool bType = sal_False, bOid = sal_False, bTid = sal_False; + sal_uInt8 nFlags = 0; + if( m_pBridgeImpl->m_lastOutType.getTypeLibType() != m_pInterfaceType->aBase.pWeakRef && + ! typelib_typedescriptionreference_equals( + m_pBridgeImpl->m_lastOutType.getTypeLibType(), m_pInterfaceType->aBase.pWeakRef ) ) + { + //new type + nFlags = nFlags | HDRFLAG_NEWTYPE; + bType = sal_True; + } + if( m_pBridgeImpl->m_lastOutOid.pData != m_pOid && + rtl_ustr_compare_WithLength( m_pBridgeImpl->m_lastOutOid.pData->buffer, + m_pBridgeImpl->m_lastOutOid.pData->length, + m_pOid->buffer, + m_pOid->length ) ) + { + //new object id + nFlags = nFlags | HDRFLAG_NEWOID; + bOid = sal_True; + } + if( m_pBridgeImpl->m_lastOutTid.getHandle() != m_pTid && + !(m_pBridgeImpl->m_lastOutTid == *(ByteSequence*) &(m_pTid) ) ) + { + // new threadid + nFlags = nFlags | HDRFLAG_NEWTID; + bTid = sal_True; + } + + if( m_bCallingConventionForced ) + { + nFlags = nFlags | HDRFLAG_MOREFLAGS; + } +#ifdef BRIDGES_URP_PROT + sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos(); +#endif + // Short request headers can only handle 14-bit method IDs, so + // unconditionally use a long header for method IDs that are too large: + if( nFlags || m_nMethodIndex >= 0xC000 ) + { + // the flag byte is needed + request + nFlags = nFlags | HDRFLAG_LONGHEADER | HDRFLAG_REQUEST; // + + // as long as we do not have customized calls, no MOREFLAGS must be set + if( m_nMethodIndex >= 0x100 ) + { + nFlags = nFlags | HDRFLAG_LONGMETHODID; + } + m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags ); + + if( nFlags & HDRFLAG_MOREFLAGS ) + { + sal_uInt8 nMoreFlags = 0; + if( ! m_bOneway ) + { + nMoreFlags = HDRFLAG_SYNCHRONOUS |HDRFLAG_MUSTREPLY; + } + m_pBridgeImpl->m_blockMarshaler.packInt8( &nMoreFlags ); + } + if( nFlags & HDRFLAG_LONGMETHODID ) + { + sal_uInt16 nMethod = (sal_uInt16 ) m_nMethodIndex; + m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod ); + } + else + { + sal_uInt8 nMethod = (sal_uInt8) m_nMethodIndex; + m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod ); + } + } + else + { + // no flag byte needed, simply marshal the method index + if( m_nMethodIndex >= 64 ) + { + sal_uInt16 nMethod = ( sal_uInt16 ) m_nMethodIndex; + nMethod = nMethod | 0x4000; + m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod ); + } + else + { + sal_uInt8 nMethod = (sal_uInt8 ) m_nMethodIndex; + m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod ); + } + } + + // marshal type,oid,tid + if( bType ) + { + m_pBridgeImpl->m_lastOutType = m_pInterfaceType->aBase.pWeakRef; + m_pBridgeImpl->m_blockMarshaler.packType( &(m_pBridgeImpl->m_lastOutType) ); + } + if( bOid ) + { + m_pBridgeImpl->m_lastOutOid = *(OUString *)&m_pOid; + m_pBridgeImpl->m_blockMarshaler.packOid( m_pBridgeImpl->m_lastOutOid ); + } + if( bTid ) + { + m_pBridgeImpl->m_lastOutTid = *(ByteSequence*)&(m_pTid); + m_pBridgeImpl->m_blockMarshaler.packTid( m_pBridgeImpl->m_lastOutTid ); + } + + if ( m_pBridgeImpl->m_properties.bCurrentContext + && m_nMethodIndex != REMOTE_RELEASE_METHOD_INDEX + && m_pContext != 0 ) + { + void * pCc = 0; + rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) ); + bSuccess = bSuccess && uno_getCurrentContext( + &pCc, aEnvName.pData, m_pContext ); + typelib_TypeDescription * pType = 0; + TYPELIB_DANGER_GET( + &pType, XCurrentContext::static_type().getTypeLibType() ); + bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( + &pCc, pType ); + TYPELIB_DANGER_RELEASE( pType ); + if ( pCc ) + { + remote_Interface * p = static_cast< remote_Interface * >( pCc ); + p->release( p ); + } + } + + // marshal arguments ! +#ifdef BRIDGES_URP_PROT + sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos(); +#endif + if( m_pMethodType ) + { + sal_Int32 i; + for( i = 0 ; i < m_pMethodType->nParams ; i ++ ) + { + if( m_pMethodType->pParams[i].bIn ) + { + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef ); + if( pType ) + { + bSuccess = + bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[i] , pType ); + TYPELIB_DANGER_RELEASE( pType ); + } + else + { + bSuccess = sal_False; + OUStringBuffer buffer( 128 ); + buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) ); + buffer.append( m_pMethodType->pParams[i].pTypeRef->pTypeName ); + m_pBridgeImpl->addError( buffer.makeStringAndClear() ); + } + } + } + } + else if( m_pAttributeType && m_pReturn ) + { + // nothing to do ! + } + else if( m_pAttributeType && m_ppArgs ) + { + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef ); + if( pType ) + { + bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[0] , pType ); + TYPELIB_DANGER_RELEASE( pType ); + } + else + { + bSuccess = sal_False; + OUStringBuffer buffer( 128 ); + buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) ); + buffer.append( m_pAttributeType->pAttributeTypeRef->pTypeName ); + m_pBridgeImpl->addError( buffer.makeStringAndClear() ); + } + } + else + { + OSL_ASSERT( 0 ); + } + +#ifdef BRIDGES_URP_PROT + urp_logCall( m_pBridgeImpl, m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart, + m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader, ! m_bOneway, + m_pMethodType ? m_pMethodType->aBase.pMemberName : + m_pAttributeType->aBase.pMemberName ); +#endif + + if( bSuccess ) + { + if( ! m_bOneway ) + { + uno_threadpool_attach( m_pBridgeImpl->m_hThreadPool ); + m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*)&(m_pTid), this ); + } + + m_pBridgeImpl->m_nMarshaledMessages ++; + //--------------------------- + // Inform the writer thread, that there is some work to do + //--------------------------- + m_pBridgeImpl->m_pWriter->touch( ! m_bOneway ); + + if( m_bOneway ) + { + *m_ppException = 0; + } + } + else + { + // Something went wrong during packing, which means, that the caches may not be in sync + // anymore. So we have no other choice than to dispose the environment. + m_pEnvRemote->dispose( m_pEnvRemote ); + OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Error during marshaling " ) ); + if( m_pMethodType ) + { + buf.append( m_pMethodType->aBase.aBase.pTypeName ); + } + else if( m_pAttributeType ) + { + buf.append( m_pAttributeType->aBase.aBase.pTypeName ); + } + buf.appendAscii( "\n" ); + buf.append( m_pBridgeImpl->getErrorsAsString() ); + prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() ); + } + return bSuccess; + // release the guard + } + + //------------------------------------------------------------------------------------ + void ClientJob::wait() + { + //--------------------------- + // Wait for the reply + //--------------------------- + void * pDisposeReason = 0; + + uno_threadpool_enter(m_pBridgeImpl->m_hThreadPool, &pDisposeReason ); + + if( ! pDisposeReason ) + { + // thread has been disposed ! + // avoid leak due continous calling on a disposed reference. The + // reply may or may not be within the container. If the reader thread + // got into problems during unmarshaling the reply for this request, + // it won't be in the container anymore, but it is eiterway safe to call + // the method + ClientJob *pJob = + m_pBridgeImpl->m_clientJobContainer.remove( *(ByteSequence*) &m_pTid ); + if( pJob != this ) + { + // this is not our job, it is probably one of the callstack below, so + // push it back + m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*) &m_pTid , pJob ); + } + + OUStringBuffer sMessage( 256 ); + sMessage.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP_Bridge : disposed\n" ) ); + sMessage.append( m_pBridgeImpl->getErrorsAsString() ); + prepareRuntimeExceptionClientSide( m_ppException, sMessage.makeStringAndClear() ); + m_bExceptionOccured = sal_True; + } + else + { + OSL_ASSERT( pDisposeReason == (void*)this ); + } + if( !m_bExceptionOccured ) + { + *m_ppException = 0; + } + uno_threadpool_detach( m_pBridgeImpl->m_hThreadPool ); + } + + //------------------------------------------------------------------------------------ + // ServerMultiJob + //------------------------------------------------------------------------------------ + ServerMultiJob::ServerMultiJob( + uno_Environment *pEnvRemote, + remote_Context *pContext, + sal_Sequence *pTid, + struct urp_BridgeImpl *pBridgeImpl, + Unmarshal *pUnmarshal, + sal_Int32 nMaxMessages ) + : Job( pEnvRemote, pContext, pTid, pBridgeImpl, pUnmarshal ) + , m_pEnvRemote( pEnvRemote ) + , m_nCalls( 0 ) + , m_nMaxMessages( nMaxMessages ) + , m_nCurrentMemPosition( 0 ) + { + m_pEnvRemote->acquire( m_pEnvRemote ); + m_nCurrentMemSize = MULTIJOB_STANDARD_MEMORY_SIZE + m_nMaxMessages * ( + MULTIJOB_PER_CALL_MEMORY_SIZE + sizeof(ServerJobEntry) + sizeof(MemberTypeInfo) ); + m_pCurrentMem = ( sal_Int8 * ) rtl_allocateMemory( m_nCurrentMemSize ); + m_aEntries = ( ServerJobEntry * ) getHeap( m_nMaxMessages * sizeof( ServerJobEntry ) ); + m_aTypeInfo = ( MemberTypeInfo * ) getHeap( m_nMaxMessages * sizeof( MemberTypeInfo ) ); + } + + ServerMultiJob::~ServerMultiJob() + { + sal_Int32 i; + for( i = 0 ; i < m_nCalls ; i ++ ) + { + struct MemberTypeInfo *const pMTI = &( m_aTypeInfo[i] ); + struct ServerJobEntry *const pSJE = &( m_aEntries[i] ); + + if( pSJE->m_pRemoteI ) + pSJE->m_pRemoteI->release( pSJE->m_pRemoteI ); + + if( pSJE->m_pOid ) + rtl_uString_release( pSJE->m_pOid ); + + if( pSJE->m_pInterfaceTypeRef ) + typelib_typedescriptionreference_release( pSJE->m_pInterfaceTypeRef ); + + if( pMTI->m_pInterfaceType ) + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)pMTI->m_pInterfaceType ); + + for( sal_Int32 iArgs = 0 ; iArgs < pMTI->m_nArgCount ; iArgs ++ ) + { + if( pMTI->m_ppArgType[iArgs] ) + TYPELIB_DANGER_RELEASE( pMTI->m_ppArgType [iArgs] ); + } + if( pMTI->m_pReturnType ) + TYPELIB_DANGER_RELEASE( pMTI->m_pReturnType ); + + if( pMTI->m_pMethodType ) + typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pMethodType ); + if( pMTI->m_pAttributeType ) + typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pAttributeType ); + } + + rtl_freeMemory( m_pCurrentMem ); + for( list< sal_Int8 *>::iterator ii = m_lstMem.begin() ; ii != m_lstMem.end() ; ++ii ) + rtl_freeMemory( *ii ); + + if( m_pEnvRemote ) + m_pEnvRemote->release( m_pEnvRemote ); + } + + //------------------------------------------------------------------------------------- + void ServerMultiJob::execute() + { + Reference< XCurrentContext > xOldCc; + bool bHasOldCc = false; + for( sal_Int32 i = 0; i < m_nCalls ; i ++ ) + { + struct MemberTypeInfo * const pMTI = &( m_aTypeInfo[i] ); + struct ServerJobEntry * const pSJE = &( m_aEntries[i] ); + + if ( pSJE->m_bHasCurrentContext ) + { + if ( !bHasOldCc ) + { + xOldCc = com::sun::star::uno::getCurrentContext(); + bHasOldCc = true; + } + rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) ); + if ( !uno_setCurrentContext( + pSJE->m_pCurrentContext, aEnvName.pData, m_pContext ) ) + { + throw RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "fatal: uno_setCurrentContext failed" ) ), + Reference< XInterface >() ); + } + if ( pSJE->m_pCurrentContext ) + { + pSJE->m_pCurrentContext->release( pSJE->m_pCurrentContext ); + } + } + + if( ! pSJE->m_pRemoteI ) + { + // ------------------- + // Initial object ? + // ------------------ + // be robust : Sending a release on a not constructed object + // provokes an segfault. Make sure, the call + // is not a release call. + remote_Context *pRemoteC = ((remote_Context*)m_pEnvRemote->pContext); + + if( ! pMTI->m_bIsReleaseCall && pRemoteC->m_pInstanceProvider ) + { + pSJE->m_pException = &(pSJE->m_exception); + + pRemoteC->m_pInstanceProvider->getInstance( + pRemoteC->m_pInstanceProvider, + m_pEnvRemote, + &(pSJE->m_pRemoteI), + pSJE->m_pOid, + pMTI->m_pInterfaceType, + &(pSJE->m_pException)); + } + else + { + prepareRuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "urp: No instance provider set")),i); + } + } + + if( pSJE->m_pException ) + { + // errors during extracting, do nothing + } + else if( ! pSJE->m_pRemoteI ) + { + // May only occur during the queryInterface call on the initial object !!! + // construct the return value + uno_type_any_construct( (uno_Any*) pSJE->m_pReturn , 0 , 0 , 0 ); + } + else + { + pSJE->m_pException = &(pSJE->m_exception ); + + if( pMTI->m_bIsReleaseCall ) + { + pSJE->m_pRemoteI->release( pSJE->m_pRemoteI ); + pSJE->m_pException = 0; + } + else + { + pSJE->m_pRemoteI->pDispatcher( + pSJE->m_pRemoteI, + pMTI->m_pMethodType ? (typelib_TypeDescription*) pMTI->m_pMethodType : + (typelib_TypeDescription*) pMTI->m_pAttributeType, + pSJE->m_pReturn, + pSJE->m_ppArgs, + &(pSJE->m_pException) ); + } + } + if( pSJE->m_pRemoteI ) + { + /** + Do the release here, in case of ForceSynchronous=1, calls + originated by the destructor of an UNO object must be sent BEFORE the + release returns ( otherwise we don't own the thread anymore ! ) + */ + pSJE->m_pRemoteI->release( pSJE->m_pRemoteI ); + pSJE->m_pRemoteI = 0; + } + + // now destruct parameters and marshal replies + // Note : when call is synchron => m_nCalls == 1 + if( pMTI->m_bIsOneway ) + { + // Oneway call, destruct in parameters + for( sal_Int32 j = 0 ; j < pMTI->m_pMethodType->nParams ; j ++ ) + { + // usually all parameters must be in parameters, but to be robust ... + if( pMTI->m_pbIsIn[j] && !cppu_isSimpleType( pMTI->m_ppArgType[j] ) ) + { + uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] , 0 ); + } + } + + if( pSJE->m_pException ) + { + uno_any_destruct( pSJE->m_pException, ::bridges_remote::remote_release ); + } + + } + else + { + // synchron, get the mutex to marshal reply and send immeadiatly + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + + sal_Bool bTid = sal_False; + sal_uInt8 nFlags = HDRFLAG_LONGHEADER; + ByteSequence tid = m_pTid; + if( !( tid == m_pBridgeImpl->m_lastOutTid ) || pSJE->m_bIgnoreCache ) + { + // new threadid + nFlags = nFlags | HDRFLAG_NEWTID; + bTid = sal_True; + } + + if( pSJE->m_pException ) + { + nFlags = nFlags | HDRFLAG_EXCEPTION; + } +#ifdef BRIDGES_URP_PROT + sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos(); +#endif + m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags ); + + if( bTid ) + { + if( ! pSJE->m_bIgnoreCache ) + { + m_pBridgeImpl->m_lastOutTid = tid; + } + m_pBridgeImpl->m_blockMarshaler.packTid( tid , pSJE->m_bIgnoreCache ); + } + +#ifdef BRIDGES_URP_PROT + sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos(); +#endif + + if( pSJE->m_pException ) + { + //-------------------- + // an exception was thrown + //-------------------- + m_pBridgeImpl->m_blockMarshaler.packAny( &(pSJE->m_exception) ); + uno_any_destruct( &(pSJE->m_exception) , ::bridges_remote::remote_release ); + + // destroy in parameters + for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ ) + { + if( pMTI->m_pbIsIn[j] && ! cppu_isSimpleType( pMTI->m_ppArgType[j] )) + { + uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] , + ::bridges_remote::remote_release ); + } + } + } + else + { + //--------------------------- + // alles ist gut ... + //-------------------------- + if( pMTI->m_pReturnType ) + { + m_pBridgeImpl->m_blockMarshaler.pack( + pSJE->m_pReturn, pMTI->m_pReturnType ); + if( ! cppu_isSimpleType( pMTI->m_pReturnType ) ) + { + uno_destructData( pSJE->m_pReturn , pMTI->m_pReturnType , + ::bridges_remote::remote_release ); + } + } + for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ ) + { + if( pMTI->m_pbIsOut[j] ) + { + m_pBridgeImpl->m_blockMarshaler.pack( + pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] ); + } + if( ! cppu_isSimpleType( pMTI->m_ppArgType[j] ) ) + { + uno_destructData( pSJE->m_ppArgs[j], pMTI->m_ppArgType[j] , + ::bridges_remote::remote_release ); + } + } + } + +#ifdef BRIDGES_URP_PROT + { + typelib_InterfaceMemberTypeDescription *pMemberType = + pMTI->m_pMethodType ? + (typelib_InterfaceMemberTypeDescription*)pMTI->m_pMethodType : + (typelib_InterfaceMemberTypeDescription*)pMTI->m_pAttributeType; + + urp_logReplying( m_pBridgeImpl , + m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart, + m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader, + pMemberType->pMemberName ); + } +#endif + + m_pBridgeImpl->m_nMarshaledMessages ++; + // put it on the wire + m_pBridgeImpl->m_pWriter->touch( sal_True ); + } // MutexGuard marshalingMutex + } + if ( bHasOldCc ) + { + if ( !com::sun::star::uno::setCurrentContext( xOldCc ) ) + { + throw RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "fatal: com::sun::star::uno::setCurrentContext" + " failed" ) ), + Reference< XInterface >() ); + } + } + } + + //------------------------------------------------------------------------------------- + void ServerMultiJob::prepareRuntimeException( const OUString & sMessage , sal_Int32 nCall ) + { + // ------------------------------- + // Construct the DisposedException + // ------------------------------- + com::sun::star::lang::DisposedException exception( sMessage , Reference< XInterface > () ); + Type type = getCppuType( &exception ); + if( !isDisposedExceptionDescriptionAvail( type ) ) + { + // if it is not available (probably missing type library), + // then we are satisfied with throwing a normal runtime exception, + // for which cppu provides a static description + type = getCppuType( ( RuntimeException * ) 0 ); + } + + m_aEntries[nCall].m_pException = &(m_aEntries[nCall].m_exception); + uno_type_any_construct( m_aEntries[nCall].m_pException , &exception , type.getTypeLibType() , 0 ); + } + + //------------------------------------------------------------------------------------- + void ServerMultiJob::initiate() + { + uno_threadpool_putJob( + m_pBridgeImpl->m_hThreadPool, + m_pTid, + this, + doit, + m_aTypeInfo[0].m_bIsOneway ); + } + + + //------------------------------------------------------------------------------------- + sal_Bool ServerMultiJob::extract() + { + sal_Bool bContinue = sal_True; + struct MemberTypeInfo * const pMTI = &(m_aTypeInfo[m_nCalls]); + struct ServerJobEntry * const pSJE = &(m_aEntries[m_nCalls]); + + pSJE->m_pException = 0; + pSJE->m_ppArgs = 0; + pSJE->m_pReturn = 0; + pMTI->m_pReturnType = 0; + + if( pMTI->m_nArgCount ) + { + pMTI->m_ppArgType = + ( typelib_TypeDescription ** ) getHeap( sizeof(void*) * pMTI->m_nArgCount ); + pSJE->m_ppArgs = (void**) getHeap( sizeof( void * ) * pMTI->m_nArgCount ); + pMTI->m_pbIsIn = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount ); + pMTI->m_pbIsOut = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount ); + } + if( pMTI->m_pMethodType && + pMTI->m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID ) + { + TYPELIB_DANGER_GET( &(pMTI->m_pReturnType), pMTI->m_pMethodType->pReturnTypeRef ); + } + else if( pMTI->m_pAttributeType && ! pMTI->m_nArgCount ) + { + TYPELIB_DANGER_GET( &(pMTI->m_pReturnType) , pMTI->m_pAttributeType->pAttributeTypeRef ); + } + + // normal method + if( pMTI->m_pMethodType ) + { + for( sal_Int32 i = 0 ; i < pMTI->m_nArgCount ; i ++ ) + { + pMTI->m_ppArgType[i] = 0; + TYPELIB_DANGER_GET( & ( pMTI->m_ppArgType[i] ) , pMTI->m_pMethodType->pParams[i].pTypeRef); + pMTI->m_pbIsIn[i] = pMTI->m_pMethodType->pParams[i].bIn; + pMTI->m_pbIsOut[i] = pMTI->m_pMethodType->pParams[i].bOut; + + pSJE->m_ppArgs[i] = getHeap( pMTI->m_ppArgType[i]->nSize ); + if( pMTI->m_pbIsIn[i] ) + { + // everything needs to be constructed + bContinue = m_pUnmarshal->unpack( + pSJE->m_ppArgs[i], pMTI->m_ppArgType[i] ) && bContinue; + } + } + } + else if( pMTI->m_nArgCount ) + { + // set attribut + pMTI->m_ppArgType[0] = 0; + pMTI->m_pbIsIn[0] = sal_True; + pMTI->m_pbIsOut[0] = sal_False; + TYPELIB_DANGER_GET( + & ( pMTI->m_ppArgType[0] ) , pMTI->m_pAttributeType->pAttributeTypeRef ); + pSJE->m_ppArgs[0] = getHeap( pMTI->m_ppArgType[0]->nSize ); + bContinue = m_pUnmarshal->unpack( + pSJE->m_ppArgs[0], pMTI->m_ppArgType[0] ) && bContinue; + } + + if( pMTI->m_pReturnType ) + { + pSJE->m_pReturn = getHeap( pMTI->m_pReturnType->nSize ); + } + + m_nCalls ++; + return bContinue; + } +} + + diff --git a/bridges/source/remote/urp/urp_job.hxx b/bridges/source/remote/urp/urp_job.hxx new file mode 100644 index 000000000000..4b769ec27f2a --- /dev/null +++ b/bridges/source/remote/urp/urp_job.hxx @@ -0,0 +1,381 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_job.hxx,v $ + * $Revision: 1.11 $ + * + * 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 _URP_JOB_HXX_ +#define _URP_JOB_HXX_ +#include <list> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> +#include <uno/environment.h> +#include <uno/threadpool.h> +#include "urp_threadid.hxx" +#include "urp_unmarshal.hxx" +#include "urp_bridgeimpl.hxx" + + +namespace bridges_urp +{ +const sal_Int32 MULTIJOB_STANDARD_MEMORY_SIZE = 1024; +const sal_Int32 MULTIJOB_PER_CALL_MEMORY_SIZE = 96; + +class Unmarshal; +struct urp_BridgeImpl; + +template < class t > +inline t mymax( const t &t1 , const t &t2 ) +{ + return t1 > t2 ? t1 : t2; +} + +class Job +{ +public: + Job( uno_Environment *pEnvRemote, + remote_Context *pContext, + sal_Sequence *pTid, + struct urp_BridgeImpl *pBridgeImpl, + Unmarshal *pUnmarshal ); + + Job( uno_Environment *pEnvRemote, + remote_Context *pContext, + struct urp_BridgeImpl *pBridgeImpl, + ::bridges_remote::RemoteThreadCounter_HoldEnvWeak value ) + : m_pContext( pContext ) + , m_pBridgeImpl( pBridgeImpl ) + , m_pTid( 0 ) + , m_counter( pEnvRemote , value ) + { + if ( m_pContext ) + { + m_pContext->aBase.acquire( &m_pContext->aBase ); + } + } + + ~Job(); + + inline void setUnmarshal( Unmarshal *p ) + { m_pUnmarshal = p; } + +public: + remote_Context *m_pContext; + Unmarshal *m_pUnmarshal; + struct urp_BridgeImpl *m_pBridgeImpl; + sal_Sequence *m_pTid; + ::bridges_remote::RemoteThreadCounter m_counter; +}; + +class ClientJob : public Job +{ +public: + // pContext is null for bridge-internal UrpProtocolProperties requests + inline ClientJob( uno_Environment *pEnvRemote, // weak ! + remote_Context *pContext, + struct urp_BridgeImpl *pBridgeImpl, + rtl_uString *pOid, // weak + typelib_TypeDescription const * pMemberType, // weak + typelib_InterfaceTypeDescription *pInterfaceType, // weak + void *pReturn, + void *ppArgs[], + uno_Any **ppException ); + + // ~ClientJob + // no release for method type and attribute type necessary, because + // it was acquired by the caller of urp_sendRequest. The lifetime + // of the ClientJob object is always shorter than the urp_sendRequest call. + inline ~ClientJob() + { + if( m_bReleaseForTypeDescriptionNecessary ) + typelib_typedescription_release( (typelib_TypeDescription*) m_pInterfaceType ); + uno_releaseIdFromCurrentThread(); + } + + sal_Bool pack(); + void wait(); + sal_Bool extract( ); + void initiate(); + + inline void setBridgePropertyCall() + { m_bBridgePropertyCall = sal_True; } + inline sal_Bool isBridgePropertyCall() + { return m_bBridgePropertyCall; } + inline sal_Bool isOneway() + { return m_bOneway; } +public: + typelib_InterfaceMethodTypeDescription *m_pMethodType; + typelib_InterfaceAttributeTypeDescription *m_pAttributeType; + sal_Bool m_bExceptionOccured; + +private: + void **m_ppArgs; + void *m_pReturn; + typelib_InterfaceTypeDescription *m_pInterfaceType; + sal_Bool m_bReleaseForTypeDescriptionNecessary; + + uno_Any **m_ppException; + sal_Bool m_bOneway; + sal_Bool m_bBridgePropertyCall; + sal_uInt16 m_nMethodIndex; + uno_Environment *m_pEnvRemote; + rtl_uString *m_pOid; + sal_Bool m_bCallingConventionForced; +}; + +struct MemberTypeInfo +{ + typelib_InterfaceTypeDescription *m_pInterfaceType; + typelib_InterfaceMethodTypeDescription *m_pMethodType; + typelib_InterfaceAttributeTypeDescription *m_pAttributeType; + sal_Int32 m_nArgCount; + sal_Bool m_bIsReleaseCall; + sal_Bool *m_pbIsIn; + sal_Bool *m_pbIsOut; + sal_Bool m_bIsOneway; + typelib_TypeDescription *m_pReturnType; + typelib_TypeDescription **m_ppArgType; +}; + + +struct ServerJobEntry +{ + rtl_uString *m_pOid; + remote_Interface *m_pRemoteI; + typelib_TypeDescriptionReference *m_pInterfaceTypeRef; + void **m_ppArgs; + void *m_pReturn; + uno_Any m_exception; + uno_Any *m_pException; + remote_Interface *m_pCurrentContext; + sal_Bool m_bHasCurrentContext; + sal_Bool m_bIgnoreCache; +}; + +class ServerMultiJob : public Job +{ +public: + ServerMultiJob( uno_Environment *pEnvRemote, + remote_Context *pContext, + sal_Sequence *pTid, + struct urp_BridgeImpl *pBridgeImpl, + Unmarshal *pUnmarshal, + sal_Int32 nMaxMessages ); + ~ServerMultiJob(); +public: + sal_Bool extract( ); + void initiate(); + void execute(); + +public: + // setMethodType or setAttributeType MUST be called before extract + inline void setMethodType( + typelib_InterfaceMethodTypeDescription *pMethodType, + sal_Bool bIsReleaseCall, + sal_Bool bIsOneway ) + { + m_aTypeInfo[m_nCalls].m_pMethodType = pMethodType; + m_aTypeInfo[m_nCalls].m_pAttributeType = 0; + m_aTypeInfo[m_nCalls].m_nArgCount = pMethodType->nParams; + m_aTypeInfo[m_nCalls].m_bIsReleaseCall = bIsReleaseCall; + m_aTypeInfo[m_nCalls].m_bIsOneway = bIsOneway; + } + + inline void setAttributeType( + typelib_InterfaceAttributeTypeDescription *pAttributeType, sal_Bool bIsSetter, sal_Bool bIsOneway ) + { + m_aTypeInfo[m_nCalls].m_pAttributeType = pAttributeType; + m_aTypeInfo[m_nCalls].m_pMethodType = 0; + m_aTypeInfo[m_nCalls].m_nArgCount = bIsSetter ? 1 : 0; + m_aTypeInfo[m_nCalls].m_bIsReleaseCall = sal_False; + m_aTypeInfo[m_nCalls].m_bIsOneway = bIsOneway; + } + + inline void setType( typelib_TypeDescriptionReference *pTypeRef ) + { + m_aEntries[m_nCalls].m_pInterfaceTypeRef = pTypeRef; + typelib_typedescriptionreference_acquire( m_aEntries[m_nCalls].m_pInterfaceTypeRef ); + TYPELIB_DANGER_GET( + (typelib_TypeDescription ** )&(m_aTypeInfo[m_nCalls].m_pInterfaceType) , + pTypeRef ); + } + // setOid or setInterface MUST be called before extract + inline void setOid( rtl_uString *pOid ) + { + m_aEntries[m_nCalls].m_pOid = pOid; + rtl_uString_acquire( m_aEntries[m_nCalls].m_pOid ); + m_aEntries[m_nCalls].m_pRemoteI = 0; + } + + // setOid or setInterface MUST be called + inline void setInterface( remote_Interface *pRemoteI ) + { + m_aEntries[m_nCalls].m_pRemoteI = pRemoteI; + pRemoteI->acquire( pRemoteI ); + m_aEntries[m_nCalls].m_pOid = 0; + } + + inline void setCurrentContext( + bool bHasCurrentContext, remote_Interface *pCurrentContext ) + { + m_aEntries[m_nCalls].m_pCurrentContext = pCurrentContext; + m_aEntries[m_nCalls].m_bHasCurrentContext = bHasCurrentContext; + } + + inline void setIgnoreCache( sal_Bool bIgnoreCache ) + { + m_aEntries[m_nCalls].m_bIgnoreCache = bIgnoreCache; + } + + inline sal_Bool isFull() + { return m_nCalls >= m_nMaxMessages; } + + inline sal_Int8 *getHeap( sal_Int32 nSizeToAlloc ) + { + if( nSizeToAlloc + m_nCurrentMemPosition > m_nCurrentMemSize ) + { + m_lstMem.push_back( m_pCurrentMem ); + m_nCurrentMemSize = mymax( nSizeToAlloc , MULTIJOB_STANDARD_MEMORY_SIZE ) + + (m_nMaxMessages -m_nCalls)*MULTIJOB_PER_CALL_MEMORY_SIZE; + m_pCurrentMem = (sal_Int8*) rtl_allocateMemory( m_nCurrentMemSize ); + m_nCurrentMemPosition = 0; + } + sal_Int8 *pHeap = m_pCurrentMem + m_nCurrentMemPosition; + m_nCurrentMemPosition += nSizeToAlloc; + + // care for alignment + if( m_nCurrentMemPosition & 0x7 ) + { + m_nCurrentMemPosition = ( ((sal_uInt32)m_nCurrentMemPosition) & ( 0xffffffff - 0x7 )) + 8; + } + return pHeap; + } + void prepareRuntimeException( const ::rtl::OUString &sMessage, sal_Int32 nCall ); + +private: + uno_Environment *m_pEnvRemote; + sal_Int32 m_nCalls; + sal_Int32 m_nMaxMessages; + + ServerJobEntry *m_aEntries; + MemberTypeInfo *m_aTypeInfo; + + sal_Int8 *m_pCurrentMem; + sal_Int32 m_nCurrentMemSize; + sal_Int32 m_nCurrentMemPosition; + + // list of memory pointers, that must be freed + ::std::list< sal_Int8 * > m_lstMem; +}; + + + +//--------------------------------------------------------------------------------------------- +inline ClientJob::ClientJob( + uno_Environment *pEnvRemote, + remote_Context *pContext, + struct urp_BridgeImpl *pBridgeImpl, + rtl_uString *pOid, + typelib_TypeDescription const * pMemberType, + typelib_InterfaceTypeDescription *pInterfaceType, + void *pReturn, + void *ppArgs[], + uno_Any **ppException ) + : Job( + pEnvRemote, pContext, pBridgeImpl, ::bridges_remote::RTC_HOLDENVWEAK ) + , m_ppArgs( ppArgs ) + , m_pReturn( pReturn ) + , m_pInterfaceType( pInterfaceType ) // weak + , m_bReleaseForTypeDescriptionNecessary( sal_False ) + , m_ppException( ppException ) + , m_bBridgePropertyCall( sal_False ) + , m_pEnvRemote( pEnvRemote ) // weak + , m_pOid( pOid ) // weak + , m_bCallingConventionForced( sal_False ) +{ + uno_getIdOfCurrentThread( &m_pTid ); + + if( typelib_TypeClass_INTERFACE_METHOD == pMemberType->eTypeClass ) + { + m_pMethodType = ( typelib_InterfaceMethodTypeDescription * ) pMemberType; + m_pAttributeType = 0; + } + else if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pMemberType->eTypeClass ) + { + m_pAttributeType = ( typelib_InterfaceAttributeTypeDescription * ) pMemberType; + m_pMethodType = 0; + } + else + { + OSL_ASSERT( ! "wrong member type" ); + } + + // calculate method index + if( ! m_pInterfaceType->aBase.bComplete ) + { + // must be acquired because typedescription may be exchanged + typelib_typedescription_acquire((typelib_TypeDescription*) m_pInterfaceType ); + m_bReleaseForTypeDescriptionNecessary = sal_True; + typelib_typedescription_complete( (typelib_TypeDescription ** ) &m_pInterfaceType ); + } + m_nMethodIndex = (sal_uInt16) m_pInterfaceType->pMapMemberIndexToFunctionIndex[ + ((typelib_InterfaceMemberTypeDescription*)pMemberType)->nPosition ]; + + if( m_pAttributeType && m_ppArgs ) + { + // setter + m_nMethodIndex ++; + } + + if( typelib_TypeClass_INTERFACE_METHOD == pMemberType->eTypeClass ) + { +// if( (( typelib_InterfaceMemberTypeDescription * ) pMemberType)->nPosition +// == REMOTE_RELEASE_METHOD_INDEX ) +// { +// m_bOneway = sal_True; +// } +// else + if( pBridgeImpl->m_properties.bForceSynchronous ) + { + m_bOneway = sal_False; + if( (( typelib_InterfaceMethodTypeDescription * ) pMemberType)->bOneWay ) + { + m_bCallingConventionForced = sal_True; + } + } + else + { + m_bOneway = (( typelib_InterfaceMethodTypeDescription * ) pMemberType)->bOneWay; + } + } + else + { + m_bOneway = sal_False; + } +} + +} +#endif diff --git a/bridges/source/remote/urp/urp_log.cxx b/bridges/source/remote/urp/urp_log.cxx new file mode 100644 index 000000000000..242503fa7221 --- /dev/null +++ b/bridges/source/remote/urp/urp_log.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_log.cxx,v $ + * $Revision: 1.6 $ + * + * 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 "urp_bridgeimpl.hxx" +#include "urp_log.hxx" + +using namespace ::rtl; +using namespace ::osl; +namespace bridges_urp +{ +#ifdef BRIDGES_URP_PROT + Mutex g_logFileMutex; + + class FileAccess + { + public: + FileAccess( urp_BridgeImpl *pBridgeImpl_ ) : + pBridgeImpl( pBridgeImpl_ ), + guard( g_logFileMutex ) + { + if( pBridgeImpl->m_pLogFile ) + { + f = pBridgeImpl->m_pLogFile; + } + else + { + f = fopen( pBridgeImpl->m_sLogFileName.getStr() , "a" ); + } + } + ~FileAccess() + { + if( ! pBridgeImpl->m_pLogFile ) + { + fclose( f ); + } + } + FILE *getFile() + { + return f; + } + private: + urp_BridgeImpl *pBridgeImpl; + MutexGuard guard; + FILE *f; + }; + + void urp_logCall( urp_BridgeImpl *pBridgeImpl, sal_Int32 nSize, sal_Int32 nUseData, sal_Bool bSynchron , + const ::rtl::OUString &sMethodName ) + { + if( pBridgeImpl->m_sLogFileName.getLength() && getenv( "PROT_REMOTE_ACTIVATE" ) ) + { + OString sOperation = OUStringToOString( sMethodName,RTL_TEXTENCODING_ASCII_US ); + + FileAccess access( pBridgeImpl ); + fprintf( access.getFile() , + "%06u: calling [size=%d(usedata=%d)] [synchron=%d] [name=%s]\n" , + static_cast< unsigned int > (osl_getGlobalTimer()), + static_cast< int > (nSize), + static_cast< int > (nUseData), + bSynchron, sOperation.pData->buffer ); + } + } + + void urp_logServingRequest( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize, sal_Int32 nUseData, sal_Bool bSynchron , + const ::rtl::OUString &sMethodName ) + { + if( pBridgeImpl->m_sLogFileName.getLength() && getenv( "PROT_REMOTE_ACTIVATE" ) ) + { + OString sOperation = OUStringToOString( sMethodName,RTL_TEXTENCODING_ASCII_US ); + + FileAccess access( pBridgeImpl ); + fprintf( + access.getFile(), + "%06u: serving request [size=%d(usedata=%d)] [synchron=%d] [name=%s]\n", + static_cast< unsigned int > (osl_getGlobalTimer()), + static_cast< int > (nSize), + static_cast< int > (nUseData), + bSynchron, + sOperation.pData->buffer + ); + } + } + + void urp_logGettingReply( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize, sal_Int32 nUseData, + const ::rtl::OUString &sMethodName ) + { + if( pBridgeImpl->m_sLogFileName.getLength() && getenv( "PROT_REMOTE_ACTIVATE" ) ) + { + OString sOperation = OUStringToOString( sMethodName,RTL_TEXTENCODING_ASCII_US ); + FileAccess access( pBridgeImpl ); + fprintf( access.getFile(), + "%06u: getting reply [size=%d(usedata=%d)][name=%s]\n" , + static_cast< unsigned int > (osl_getGlobalTimer()), + static_cast< int > (nSize), + static_cast< int > (nUseData), + sOperation.pData->buffer); + } + } + + void urp_logReplying( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize , sal_Int32 nUseData, + const ::rtl::OUString &sMethodName ) + { + if( pBridgeImpl->m_sLogFileName.getLength() && getenv( "PROT_REMOTE_ACTIVATE" ) ) + { + OString sOperation = OUStringToOString(sMethodName,RTL_TEXTENCODING_ASCII_US); + + FileAccess access( pBridgeImpl ); + fprintf( access.getFile(), + "%06u: replying [size=%d(usedata=%d)] [name=%s]\n", + static_cast< unsigned int > (osl_getGlobalTimer()), + static_cast< int > (nSize), + static_cast< int > (nUseData), + sOperation.pData->buffer); + } + } +#endif +} diff --git a/bridges/source/remote/urp/urp_log.hxx b/bridges/source/remote/urp/urp_log.hxx new file mode 100644 index 000000000000..6c96ea0dbffc --- /dev/null +++ b/bridges/source/remote/urp/urp_log.hxx @@ -0,0 +1,53 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_log.hxx,v $ + * $Revision: 1.7 $ + * + * 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. + * + ************************************************************************/ +namespace bridges_urp +{ +#ifdef DBG_UTIL +#define BRIDGES_URP_PROT +#endif + +#ifdef BRIDGES_URP_PROT + void urp_logCall( urp_BridgeImpl *pBridgeImpl , + sal_Int32 nSize, sal_Int32 nUseData, sal_Bool bSynchron , + const ::rtl::OUString &sMethodName ); + + void urp_logServingRequest( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize, sal_Int32 nUseData, sal_Bool bSynchron , + const ::rtl::OUString &sMethodName ); + + void urp_logGettingReply( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize, sal_Int32 nUseData, + const ::rtl::OUString &sMethodName ); + + void urp_logReplying( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nSize , sal_Int32 nUseData, + const ::rtl::OUString &sMethodName ); +#endif +} diff --git a/bridges/source/remote/urp/urp_marshal.cxx b/bridges/source/remote/urp/urp_marshal.cxx new file mode 100644 index 000000000000..3931eda4908f --- /dev/null +++ b/bridges/source/remote/urp/urp_marshal.cxx @@ -0,0 +1,238 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_marshal.cxx,v $ + * $Revision: 1.7 $ + * + * 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/diagnose.h> +#include <rtl/alloc.h> + +#include <uno/any2.h> +#include <uno/sequence2.h> + +#include "urp_marshal.hxx" + +using namespace ::rtl; + +using namespace ::com::sun::star::uno; + +namespace bridges_urp { + +static int g_nDetectLittleEndian = 1; +char g_bMarshalSystemIsLittleEndian = ((char*)&g_nDetectLittleEndian)[0]; + +Marshal::Marshal( urp_BridgeImpl *pBridgeImpl, + sal_Int32 nBufferSize, + urp_extractOidCallback callback) : + m_nBufferSize( nBufferSize ), + m_base( (sal_Int8*)rtl_allocateMemory( nBufferSize ) ), + m_pos( m_base + 2*sizeof( sal_Int32 ) ), + m_pBridgeImpl( pBridgeImpl ), + m_callback( callback ) +{} + +Marshal::~Marshal( ) +{ + rtl_freeMemory( m_base ); +} + +void Marshal::packOid( const ::rtl::OUString & oid ) +{ + sal_uInt16 nIndex; + if( oid.getLength() ) + { + nIndex = m_pBridgeImpl->m_oidCacheOut.seek( oid ); + if( 0xffff == nIndex ) + { + nIndex = m_pBridgeImpl->m_oidCacheOut.put( oid ); + packString( (void*)(&oid.pData) ); + } + else + { + OUString dummy; + packString( &dummy ); + } + } + else + { + // null reference + nIndex = 0xffff; + OUString dummy; + packString( &dummy ); + } + packInt16( &nIndex ); +} + +void Marshal::packTid( const ByteSequence & threadId, sal_Bool bIgnoreCache ) +{ + + sal_uInt16 nIndex = 0xffff; + if( ! bIgnoreCache ) + { + nIndex = m_pBridgeImpl->m_tidCacheOut.seek( threadId ); + } + + if( 0xffff == nIndex ) + { + if( ! bIgnoreCache ) + { + nIndex = m_pBridgeImpl->m_tidCacheOut.put( threadId ); + } + packByteSequence( (sal_Int8*) threadId.getConstArray() ,threadId.getLength()); + } + else + { + packByteSequence( 0 , 0 ); + } + packInt16( &nIndex ); +} + + +void Marshal::packType( void *pSource ) +{ + typelib_TypeDescriptionReference *pRef = + *(typelib_TypeDescriptionReference ** ) pSource; + + OSL_ASSERT( pRef ); + + sal_uInt8 nTypeClass = ( sal_uInt8 ) pRef->eTypeClass; + + if( nTypeClass <= /* any*/ 14 ) + { + packInt8( (sal_Int8*)&nTypeClass ); + } + else + { + OUString sTypeName; + sal_uInt16 nIndex = 0xffff; + + nIndex = m_pBridgeImpl->m_typeCacheOut.seek( *(Type*)&pRef ); + if( 0xffff == nIndex ) + { + // put it into the cache + nIndex = m_pBridgeImpl->m_typeCacheOut.put( *(Type*)&pRef ); + sTypeName = pRef->pTypeName; + nTypeClass = nTypeClass | 0x80; + } + packInt8( &nTypeClass ); + packInt16( &nIndex ); + if( 0x80 & nTypeClass ) + { + packString( &sTypeName ); + } + } +} + +sal_Bool Marshal::packRecursive( void *pSource , typelib_TypeDescription *pType ) +{ + sal_Bool bSuccess = sal_True; + switch( pType->eTypeClass ) + { + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_STRUCT: + { + typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription*)pType; + + if (pCompType->pBaseTypeDescription) + { + bSuccess = pack( pSource , (typelib_TypeDescription*) pCompType->pBaseTypeDescription ); + } + + // then construct members + typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs; + sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets; + sal_Int32 nDescr = pCompType->nMembers; + + for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) + { + typelib_TypeDescription * pMemberType = 0; + TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] ); + if( pMemberType ) + { + bSuccess = bSuccess && pack( (char*)pSource + pMemberOffsets[nPos] , pMemberType ); + TYPELIB_DANGER_RELEASE( pMemberType ); + } + else + { + OUStringBuffer buf( 64 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Couldn't get typedescription for type ")); + buf.append( ppTypeRefs[nPos]->pTypeName ); + m_pBridgeImpl->addError( buf.makeStringAndClear() ); + bSuccess = sal_False; + } + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + typelib_IndirectTypeDescription *pIndirectType = + ( typelib_IndirectTypeDescription* ) pType; + + const sal_Int32 nElements = (*(uno_Sequence **)pSource)->nElements; + char * pSourceElements = (char *)(*(uno_Sequence **)pSource)->elements; + + if( typelib_TypeClass_BYTE == pIndirectType->pType->eTypeClass ) + { + // Byte sequences are optimized + packByteSequence( (sal_Int8*)pSourceElements , nElements ); + } + else + { + typelib_TypeDescription *pElementType = 0; + TYPELIB_DANGER_GET( &pElementType, pIndirectType->pType ); + if( pElementType ) + { + const sal_Int32 nElementSize = pElementType->nSize; + + packCompressedSize( nElements ); + for ( sal_Int32 i = 0 ; i < nElements; i++ ) + { + bSuccess = bSuccess && pack( pSourceElements + (nElementSize*i) , pElementType ); + } + TYPELIB_DANGER_RELEASE( pElementType ); + } + else + { + bSuccess = sal_False; + OUStringBuffer buf( 64 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Couldn't get typedescription for type ")); + buf.append( pIndirectType->pType->pTypeName ); + m_pBridgeImpl->addError( buf.makeStringAndClear() ); + } + } + break; + } + default: + OSL_ASSERT( 0 ); + } + return bSuccess; +} + +} // end namespace bridges diff --git a/bridges/source/remote/urp/urp_marshal.hxx b/bridges/source/remote/urp/urp_marshal.hxx new file mode 100644 index 000000000000..30cfad42cdd9 --- /dev/null +++ b/bridges/source/remote/urp/urp_marshal.hxx @@ -0,0 +1,346 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_marshal.hxx,v $ + * $Revision: 1.9 $ + * + * 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 _URP_MARSHAL_HXX_ +#define _URP_MARSHAL_HXX_ +#include <rtl/ustrbuf.hxx> +#include <rtl/byteseq.hxx> +#include <com/sun/star/uno/Type.hxx> +#include "urp_bridgeimpl.hxx" +#include "urp_marshal_decl.hxx" + +#include <string.h> + +struct remote_Interface; + +namespace bridges_urp +{ + // methods for accessing marshaling buffer + inline void Marshal::finish( sal_Int32 nMessageCount ) + { + sal_Int32 nSize = getSize() - 2*sizeof( sal_Int32 ); + + // save the state + sal_Int8 *pos = m_pos; + m_pos = m_base; + packInt32( &nSize ); + packInt32( &nMessageCount ); + + // reset the state + m_pos = pos; + } + + inline void Marshal::restart() + { + m_pos = m_base + 2*sizeof( sal_Int32 ); + } + + inline sal_Int8 *Marshal::getBuffer() + { + return m_base; + } + + inline sal_Bool Marshal::empty() const + { + return ( m_pos - m_base ) == 2*sizeof( sal_Int32 ); + } + + inline sal_Int32 Marshal::getSize() + { + return ((sal_Int32) (m_pos - m_base)); + } + + inline void Marshal::ensureAdditionalMem( sal_Int32 nMemToAdd ) + { + sal_Int32 nDiff = m_pos - m_base; + if( nDiff + nMemToAdd > m_nBufferSize ) + { + m_nBufferSize = m_nBufferSize * 2 > nDiff + nMemToAdd ? + m_nBufferSize* 2 : + nDiff + nMemToAdd; + + m_base = ( sal_Int8 * ) rtl_reallocateMemory( m_base , m_nBufferSize ); + m_pos = m_base + nDiff; + } + } + + // marshaling methods + inline void Marshal::packInt8( void *pSource ) + { + ensureAdditionalMem( 1 ); + *m_pos = *((sal_Int8*) pSource ); + m_pos++; + } + + inline void Marshal::packInt16( void *pSource ) + { + ensureAdditionalMem( 2 ); + if( isSystemLittleEndian() ) + { + m_pos[0] = ((unsigned char *)pSource)[1]; + m_pos[1] = ((unsigned char *)pSource)[0]; + } + else + { + m_pos[1] = ((unsigned char *)pSource)[1]; + m_pos[0] = ((unsigned char *)pSource)[0]; + } + m_pos +=2; + } + + inline void Marshal::packByteSequence( sal_Int8 *pData , sal_Int32 nLength ) + { + packCompressedSize( nLength ); + + ensureAdditionalMem( nLength ); + memcpy( m_pos , pData , nLength ); + m_pos += nLength; + } + + inline void Marshal::packString( void *pSource ) + { + rtl_uString *p = *( rtl_uString ** ) pSource; + + // to be optimized ! + // static buffer in marshal + ::rtl::OString o = ::rtl::OUStringToOString( p , RTL_TEXTENCODING_UTF8 ); + sal_Int32 nLength = o.pData->length; + packCompressedSize( nLength ); + + ensureAdditionalMem( nLength ); + + memcpy( m_pos , o.pData->buffer , nLength ); + m_pos += nLength; + } + + inline sal_Bool Marshal::packAny( void *pSource ) + { + sal_Bool bSuccess = sal_True; + uno_Any *pAny = (uno_Any * ) pSource; + + // pack the type + packType( &( pAny->pType ) ); + // pack the value + typelib_TypeDescription *pType = 0; + TYPELIB_DANGER_GET( &pType, pAny->pType ); + if( pType ) + { + pack( pAny->pData , pType ); + TYPELIB_DANGER_RELEASE( pType ); + } + else + { + rtl::OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("couldn't get typedescription for type " ) ); + buf.append( pAny->pType->pTypeName ); + m_pBridgeImpl->addError( buf.makeStringAndClear() ); + bSuccess = sal_False; + } + return bSuccess; + } + + inline void Marshal::packInt32( void *pSource ) + { + ensureAdditionalMem( 4 ); + if( isSystemLittleEndian() ) + { + m_pos[0] = ((unsigned char *)pSource)[3]; + m_pos[1] = ((unsigned char *)pSource)[2]; + m_pos[2] = ((unsigned char *)pSource)[1]; + m_pos[3] = ((unsigned char *)pSource)[0]; + } + else { + m_pos[3] = ((unsigned char *)pSource)[3]; + m_pos[2] = ((unsigned char *)pSource)[2]; + m_pos[1] = ((unsigned char *)pSource)[1]; + m_pos[0] = ((unsigned char *)pSource)[0]; + } + m_pos +=4; + } + + inline void Marshal::packCompressedSize( sal_Int32 nSize ) + { + ensureAdditionalMem( 5 ); + + if( nSize < 0xff ) + { + *((sal_uInt8*)m_pos) = (sal_uInt8) nSize; + m_pos ++; + } + else + { + *((sal_uInt8*)m_pos) = 0xff; + m_pos ++; + packInt32( &nSize ); + } + } + + inline sal_Bool Marshal::pack( void *pSource , typelib_TypeDescription *pType ) + { + sal_Bool bSuccess = sal_True; + switch( pType->eTypeClass ) + { + case typelib_TypeClass_BYTE: + { + packInt8( pSource ); + break; + } + case typelib_TypeClass_BOOLEAN: + { + ensureAdditionalMem( 1 ); + *m_pos = ( *((sal_Bool*) pSource ) ) ? 1 : 0; + m_pos++; + break; + } + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + { + packInt16( pSource ); + break; + } + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_FLOAT: + { + packInt32( pSource ); + break; + } + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + { + ensureAdditionalMem( 8 ); + if( isSystemLittleEndian() ) + { + m_pos[0] = ((unsigned char *)pSource)[7]; + m_pos[1] = ((unsigned char *)pSource)[6]; + m_pos[2] = ((unsigned char *)pSource)[5]; + m_pos[3] = ((unsigned char *)pSource)[4]; + m_pos[4] = ((unsigned char *)pSource)[3]; + m_pos[5] = ((unsigned char *)pSource)[2]; + m_pos[6] = ((unsigned char *)pSource)[1]; + m_pos[7] = ((unsigned char *)pSource)[0]; + } + else + { + m_pos[7] = ((unsigned char *)pSource)[7]; + m_pos[6] = ((unsigned char *)pSource)[6]; + m_pos[5] = ((unsigned char *)pSource)[5]; + m_pos[4] = ((unsigned char *)pSource)[4]; + m_pos[3] = ((unsigned char *)pSource)[3]; + m_pos[2] = ((unsigned char *)pSource)[2]; + m_pos[1] = ((unsigned char *)pSource)[1]; + m_pos[0] = ((unsigned char *)pSource)[0]; + } + m_pos += 8; + break; + } + + case typelib_TypeClass_STRING: + { + packString( pSource ); + break; + } + case typelib_TypeClass_TYPE: + { + packType( pSource ); + break; + } + case typelib_TypeClass_ANY: + { + bSuccess = packAny( pSource ); + break; + } + case typelib_TypeClass_TYPEDEF: + { + bSuccess = sal_False; + m_pBridgeImpl->addError( "can't handle typedef typedescriptions" ); + break; + } + case typelib_TypeClass_INTERFACE: + { + remote_Interface *pRemoteI = *( remote_Interface ** )pSource; + + ::rtl::OUString sOid; + sal_uInt16 nIndex = 0xffff; + if( pRemoteI ) + { + m_callback( pRemoteI , &(sOid.pData) ); + + nIndex = m_pBridgeImpl->m_oidCacheOut.seek( sOid ); + if( 0xffff == nIndex ) + { + nIndex = m_pBridgeImpl->m_oidCacheOut.put( sOid ); + } + else + { + // cached ! + sOid = ::rtl::OUString(); + } + } + packString( &sOid ); + packInt16( &nIndex ); + break; + } + case typelib_TypeClass_VOID: + { + // do nothing + break; + } + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_SEQUENCE: + { + bSuccess = packRecursive( pSource, pType ); + break; + } + default: + { + bSuccess = sal_False; + rtl::OUStringBuffer buf( 128 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "can't handle values with typeclass " ) ); + buf.append( (sal_Int32 ) pType->eTypeClass , 10 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) ); + buf.append( pType->pTypeName ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) ); + m_pBridgeImpl->addError( buf.makeStringAndClear() ); + break; + } + } + return bSuccess; + } +} + + + +#endif + diff --git a/bridges/source/remote/urp/urp_marshal_decl.hxx b/bridges/source/remote/urp/urp_marshal_decl.hxx new file mode 100644 index 000000000000..a5d5e943fd65 --- /dev/null +++ b/bridges/source/remote/urp/urp_marshal_decl.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_marshal_decl.hxx,v $ + * $Revision: 1.6 $ + * + * 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 _URP_MARSHAL_DECL_HXX_ +#define _URP_MARSHAL_DECL_HXX_ + +#include <rtl/ustring.hxx> +#include <rtl/byteseq.hxx> + +#include <com/sun/star/uno/Type.hxx> + +namespace bridges_urp +{ + struct urp_BridgeImpl; + + typedef void + ( SAL_CALL * urp_extractOidCallback )( remote_Interface *pRemoteI, rtl_uString **ppOid ); + + extern char g_bMarshalSystemIsLittleEndian; + class Marshal + { + public: + Marshal( /* cache access */ struct urp_BridgeImpl *, + sal_Int32 m_nBufferSize, + urp_extractOidCallback callback = 0 + ); + ~Marshal( ); + + inline sal_Bool pack( void *pSource , typelib_TypeDescription *pType ); + + sal_Bool packRecursive( void *pSource, typelib_TypeDescription *pType ); + + void packTid( const ::rtl::ByteSequence &id, sal_Bool bIgnoreCache = sal_False ); + void packOid( const ::rtl::OUString &oid ); + void packType( void *pSource ); + + inline void packCompressedSize( sal_Int32 nSize ); + inline void packInt8( void *pSource ); + inline void packInt16( void *pSource ); + inline void packInt32( void *pSource ); + inline void packString( void *pSource ); + inline sal_Bool packAny( void *pSource ); + inline void packByteSequence( sal_Int8 *pBuffer , sal_Int32 nSize ); + + // can be called during marshaling, but not between + // finish and restart + // returns true, when nothing has been marshaled + inline sal_Bool empty() const; + + // stops marshaling, inserts size in front of the buffer + // getStart and getSize can now be called + inline void finish( sal_Int32 nMessageCount ); + + // must be called after finish. After calling restart, + // a new marshalling session is started invalidating + // the previous bufer + inline void restart(); + + // is only valid, after finish has been called. + // valid until destructed. + inline sal_Int8 *getBuffer(); + + // is only valid, after finish has been called. + // valid until destructed. + inline sal_Int32 getSize(); + + inline sal_Int32 getPos() + { return m_pos - m_base; } + + inline sal_Bool isSystemLittleEndian() + { return g_bMarshalSystemIsLittleEndian; } + + private: + inline void ensureAdditionalMem( sal_Int32 nMemToAdd ); + sal_Int32 m_nBufferSize; + sal_Int8 *m_base; + sal_Int8 *m_pos; + struct urp_BridgeImpl *m_pBridgeImpl; + urp_extractOidCallback m_callback; + }; +} +#endif diff --git a/bridges/source/remote/urp/urp_property.hxx b/bridges/source/remote/urp/urp_property.hxx new file mode 100644 index 000000000000..0b3f1ea560da --- /dev/null +++ b/bridges/source/remote/urp/urp_property.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_property.hxx,v $ + * $Revision: 1.8 $ + * + * 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 _URP_PROPERTY_HXX_ +#define _URP_PROPERTY_HXX_ +#ifndef _BRIDGES_REMOTE_REMOTE_H_ +#include <bridges/remote/remote.h> +#endif +#include <rtl/ustring.hxx> +#include <rtl/byteseq.hxx> + +namespace bridges_urp +{ + struct Properties + { + ::rtl::ByteSequence seqBridgeID; + sal_Int32 nTypeCacheSize; + sal_Int32 nOidCacheSize; + sal_Int32 nTidCacheSize; + ::rtl::OUString sSupportedVersions; + ::rtl::OUString sVersion; + sal_Int32 nFlushBlockSize; + sal_Int32 nOnewayTimeoutMUSEC; + sal_Bool bSupportsMustReply; + sal_Bool bSupportsSynchronous; + sal_Bool bSupportsMultipleSynchronous; + sal_Bool bClearCache; + sal_Bool bNegotiate; + sal_Bool bForceSynchronous; + sal_Bool bCurrentContext; + + inline Properties() + : nTypeCacheSize( 256 ) + , nOidCacheSize( 256 ) + , nTidCacheSize( 256 ) + , sSupportedVersions( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1.0" ) ) ) + , sVersion( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1.0" ))) + , nFlushBlockSize( 4*1024 ) + , nOnewayTimeoutMUSEC( 10000 ) + , bSupportsMustReply( sal_False ) + , bSupportsSynchronous( sal_False ) + , bSupportsMultipleSynchronous( sal_False ) + , bClearCache( sal_False ) + , bNegotiate( sal_True ) + , bForceSynchronous( sal_True ) + , bCurrentContext( sal_False ) + {} + + inline Properties & SAL_CALL operator = ( const Properties &props ) + { + seqBridgeID = props.seqBridgeID; + nTypeCacheSize = props.nTypeCacheSize; + nOidCacheSize = props.nOidCacheSize; + nTidCacheSize = props.nTidCacheSize; + sSupportedVersions = props.sSupportedVersions; + sVersion = props.sVersion; + nFlushBlockSize = props.nFlushBlockSize; + nOnewayTimeoutMUSEC = props.nOnewayTimeoutMUSEC; + bSupportsMustReply = props.bSupportsMustReply; + bSupportsSynchronous = props.bSupportsSynchronous; + bSupportsMultipleSynchronous = props.bSupportsMultipleSynchronous; + bClearCache = props.bClearCache; + bNegotiate = props.bNegotiate; + bForceSynchronous = props.bForceSynchronous; + bCurrentContext = props.bCurrentContext; + return *this; + } + }; +} // end namespace bridges_urp +#endif diff --git a/bridges/source/remote/urp/urp_propertyobject.cxx b/bridges/source/remote/urp/urp_propertyobject.cxx new file mode 100644 index 000000000000..fa5fd4252490 --- /dev/null +++ b/bridges/source/remote/urp/urp_propertyobject.cxx @@ -0,0 +1,796 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_propertyobject.cxx,v $ + * $Revision: 1.11.20.1 $ + * + * 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 <stdlib.h> +#include <osl/diagnose.h> + +#include <rtl/random.h> + +#include <uno/data.h> + +#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp" +#include <com/sun/star/bridge/XProtocolProperties.hpp> + +#include "urp_propertyobject.hxx" +#include "urp_dispatch.hxx" +#include "urp_bridgeimpl.hxx" +#include "urp_job.hxx" + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::uno; + +using namespace bridges_urp; + +extern "C" { + +static void SAL_CALL staticAcquire( remote_Interface *pRemoteI ) +{ + PropertyObject *pProperties = (PropertyObject *) pRemoteI; + pProperties->thisAcquire(); +} + +static void SAL_CALL staticRelease( remote_Interface *pRemoteI ) +{ + PropertyObject *pProperties = (PropertyObject *) pRemoteI; + pProperties->thisRelease(); +} + +static void SAL_CALL staticDispatch( + remote_Interface * pRemoteI, typelib_TypeDescription const * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + PropertyObject *pProperties = (PropertyObject *) pRemoteI; + pProperties->thisDispatch( pMemberType, pReturn, pArgs, ppException ); +} + +} + +namespace bridges_urp +{ +// some nice constants .... +static const sal_Int32 METHOD_QUERY_INTERFACE = 0; +static const sal_Int32 METHOD_GET_PROPERTIES = 3; +static const sal_Int32 METHOD_REQUEST_CHANGE = 4; +static const sal_Int32 METHOD_COMMIT_CHANGE = 5; + +static const sal_Int32 PROPERTY_BRIDGEID = 0; +static const sal_Int32 PROPERTY_TYPECACHESIZE = 1; +static const sal_Int32 PROPERTY_OIDCACHESIZE = 2; +static const sal_Int32 PROPERTY_TIDCACHESIZE = 3; +static const sal_Int32 PROPERTY_SUPPORTEDVERSIONS = 4; +static const sal_Int32 PROPERTY_VERSION =5; +static const sal_Int32 PROPERTY_FLUSHBLOCKSIZE = 6; +static const sal_Int32 PROPERTY_ONEWAYTIMEOUT_MUSEC = 7; +static const sal_Int32 PROPERTY_SUPPORTSMUSTREPLY = 8; +static const sal_Int32 PROPERTY_SUPPERTSSYNCHRONOUS = 9; +static const sal_Int32 PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS = 10; +static const sal_Int32 PROPERTY_CLEARCACHE = 11; +static const sal_Int32 PROPERTY_NEGOTIATE = 12; +static const sal_Int32 PROPERTY_FORCESYNCHRONOUS = 13; +static const sal_Int32 PROPERTY_CURRENTCONTEXT = 14; + +static const sal_Int32 MAX_PROPERTIES = PROPERTY_CURRENTCONTEXT +1; + +const sal_Char *g_aPropertyName[] = +{ + "BridgeId", + "TypeCacheSize", + "OidCacheSize", + "TidCacheSize", + "SupportedVersion", + "Version", + "FlushBlockSize", + "OnewayTimeoutMUSEC", + "SupportsMustReply", + "SupportsSynchronous", + "SupportsMultipleSynchronous", + "ClearCache", + "Negotiate", + "ForceSynchronous", + "CurrentContext" +}; + +// nice little helper functions for conversion +template< class t > +void assignToIdl( ProtocolProperty *pIdl, sal_Int32 nIndex, const t &value ) +{ + pIdl->Name = OUString::createFromAscii( g_aPropertyName[nIndex] ); + ( *(::com::sun::star::uno::Any *)&(pIdl->Value) ) <<= value; +} + +template< class t > +void assignFromIdl( t * p, const ProtocolProperty & property ) +{ + property.Value >>=*p; +} + +static sal_Int32 getIndexFromIdl( const ProtocolProperty & property ) +{ + sal_Int32 nResult = -1; + for( sal_Int32 i = 0 ; i < MAX_PROPERTIES ; i ++ ) + { + if( 0 == property.Name.compareToAscii( g_aPropertyName[i] ) ) + { + nResult = i; + break; + } + } + return nResult; +} + +static sal_Int32 getIndexFromString( const OUString & property ) +{ + sal_Int32 nResult = -1; + for( sal_Int32 i = 0 ; i < MAX_PROPERTIES ; i ++ ) + { + if( 0 == property.compareToAscii( g_aPropertyName[i] ) ) + { + nResult = i; + break; + } + } + return nResult; +} + +static sal_Bool assignFromIdlToStruct( Properties *pProps, const ProtocolProperty &idl ) +{ + sal_Bool bReturn = sal_True; + + sal_Int32 nIndex = getIndexFromIdl( idl ); + if( nIndex >= 0 ) + { + switch( nIndex ) + { + case PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS: + assignFromIdl( &(pProps->bSupportsMultipleSynchronous) , idl ); + break; + case PROPERTY_SUPPERTSSYNCHRONOUS: + assignFromIdl( &(pProps->bSupportsMustReply) , idl ); + break; + case PROPERTY_SUPPORTSMUSTREPLY: + assignFromIdl( &(pProps->bSupportsSynchronous) , idl ); + break; + case PROPERTY_ONEWAYTIMEOUT_MUSEC: + assignFromIdl( &(pProps->nOnewayTimeoutMUSEC) , idl ); + break; + case PROPERTY_BRIDGEID: + assignFromIdl( (Sequence< sal_Int8 > * )&(pProps->seqBridgeID), idl ); + break; + case PROPERTY_TYPECACHESIZE: + assignFromIdl( &(pProps->nTypeCacheSize) , idl ); + break; + case PROPERTY_OIDCACHESIZE: + assignFromIdl( &(pProps->nOidCacheSize) , idl ); + break; + case PROPERTY_TIDCACHESIZE: + assignFromIdl( &(pProps->nTidCacheSize), idl ); + break; + case PROPERTY_SUPPORTEDVERSIONS: + assignFromIdl( &(pProps->sSupportedVersions) , idl ); + break; + case PROPERTY_VERSION: + assignFromIdl( &(pProps->sVersion) , idl ); + break; + case PROPERTY_FLUSHBLOCKSIZE: + assignFromIdl( &(pProps->nFlushBlockSize) ,idl ); + break; + case PROPERTY_CLEARCACHE: + assignFromIdl( &(pProps->bClearCache) ,idl ); + break; + case PROPERTY_NEGOTIATE: + assignFromIdl( &(pProps->bNegotiate) ,idl ); + break; + case PROPERTY_FORCESYNCHRONOUS: + assignFromIdl( &(pProps->bForceSynchronous) ,idl ); + break; + case PROPERTY_CURRENTCONTEXT: + pProps->bCurrentContext = true; + break; + default: + bReturn = sal_False; + } + } + else + { + bReturn = sal_False; + } + return bReturn; +} + +static void extractTokens( + const ::rtl::OUString &sProps , ::std::list< OUString > &lst ) +{ + sal_Int32 nNext = 0; + while ( sal_True ) + { + sal_Int32 nStart = nNext; + nNext = sProps.indexOf( ',' , nNext ); + if( -1 == nNext ) + { + lst.push_back( sProps.copy( nStart, sProps.getLength() - nStart ) ); + break; + } + lst.push_back( sProps.copy( nStart , nNext - nStart ) ); + nNext ++; + } +} + + +static void assignFromStringToPropSeq( const OUString &sProps, uno_Sequence **ppPropertySeq) +{ + ::std::list< OUString > lst; + extractTokens( sProps , lst ); + + typelib_TypeDescription *pSequenceType = 0; + getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pSequenceType ); + uno_Sequence *pSeq = 0; + uno_sequence_construct( &pSeq , pSequenceType , 0, lst.size() , 0 ); + ProtocolProperty *pElements = (ProtocolProperty * ) pSeq->elements; + + sal_Int32 i = 0; + for( ::std::list< OUString >::iterator ii = lst.begin() ; ii != lst.end() ; ++ ii, i++ ) + { + sal_Int32 nAssign = (*ii).indexOf( '=' ); + if( -1 == nAssign ) + { + OString o = OUStringToOString( *ii, RTL_TEXTENCODING_ASCII_US ); + OSL_ENSURE( !"wrong protocol propertyt format, ignored", o.getStr() ); + } + OUString sPropName = (*ii).copy( 0, nAssign ); + OUString sValue = (*ii).copy( nAssign +1, (*ii).getLength() - nAssign -1 ); + + sal_Int32 nIndex = getIndexFromString( sPropName ); + if( -1 == nIndex ) + { + OString o = OUStringToOString( sPropName , RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE( !"unknown protocol property, ignored", o.getStr() ); + } + switch( nIndex ) + { + // voids + case PROPERTY_CURRENTCONTEXT: + pElements[i].Name = OUString::createFromAscii( + g_aPropertyName[nIndex] ); + break; + // bools + case PROPERTY_CLEARCACHE: + case PROPERTY_NEGOTIATE: + case PROPERTY_FORCESYNCHRONOUS: + { + sal_Bool bClearCache = (sal_Bool ) sValue.toInt32(); + assignToIdl( &(pElements[i]) , nIndex , bClearCache ); + break; + } + // ints + case PROPERTY_TYPECACHESIZE: + case PROPERTY_OIDCACHESIZE: + case PROPERTY_TIDCACHESIZE: + case PROPERTY_FLUSHBLOCKSIZE: + case PROPERTY_ONEWAYTIMEOUT_MUSEC: + { + sal_Int32 nValue = sValue.toInt32(); + assignToIdl( &(pElements[i]) , nIndex , nValue ); + break; + } + + // strings + case PROPERTY_VERSION: + assignToIdl( &(pElements[i]) , nIndex , sValue ); + break; + default: + OString o = OUStringToOString( sPropName, RTL_TEXTENCODING_ASCII_US ); + OSL_ENSURE( !"readonly protocol property, ignored" , o.getStr() ); + } + } + *ppPropertySeq = pSeq; + typelib_typedescription_release( pSequenceType ); +} + +static void assignFromPropSeqToStruct( uno_Sequence *pSeq , struct Properties *pProps ) +{ + sal_Int32 i; + ProtocolProperty *pElements = (ProtocolProperty *)pSeq->elements; + for( i = 0 ; i < pSeq->nElements ; i ++ ) + { + assignFromIdlToStruct( pProps , pElements[i] ); + } +} + +void assignFromStringToStruct( const OUString & sProps , struct Properties *pProps ) +{ + uno_Sequence *pSeq = 0; + assignFromStringToPropSeq( sProps , &pSeq ); + assignFromPropSeqToStruct( pSeq , pProps ); + uno_type_destructData( &pSeq, getCppuType( (Sequence< ProtocolProperty > *)0).getTypeLibType(),0); +} + + +//---------------------------------------------------------------------------------------------- +// PropertyObject implementation +PropertyObject::PropertyObject( + struct Properties *pLocalSetting , uno_Environment *pEnvRemote, urp_BridgeImpl *pImpl ) + : m_commitChangeCondition( osl_createCondition() ) + , m_nRefCount( 0 ) + , m_pBridgeImpl( pImpl ) + , m_pLocalSetting( pLocalSetting ) + , m_pEnvRemote( pEnvRemote ) + , m_bRequestChangeHasBeenCalled( sal_False ) + , m_bServerWaitingForCommit( sal_False ) + , m_bApplyProperties( sal_False ) +{ + acquire = staticAcquire; + release = staticRelease; + pDispatcher = staticDispatch; +} + +PropertyObject::~PropertyObject() +{ + osl_destroyCondition( m_commitChangeCondition ); +} + +void SAL_CALL PropertyObject::thisDispatch( + typelib_TypeDescription const * pMemberType, void * pReturn, void * ppArgs[], + uno_Any ** ppException ) +{ + OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ); + + typelib_InterfaceMethodTypeDescription *pMethodType = + ( typelib_InterfaceMethodTypeDescription * ) pMemberType; + + switch( pMethodType->aBase.nPosition ) + { + case METHOD_QUERY_INTERFACE: + OSL_ENSURE( 0 , "not implemented yet !" ); + break; + case METHOD_GET_PROPERTIES: + { + implGetProperties( (uno_Sequence **) pReturn ); + *ppException = 0; + break; + } + case METHOD_COMMIT_CHANGE: + { + implCommitChange( *(uno_Sequence ** ) ppArgs[0] , ppException ); + break; + } + case METHOD_REQUEST_CHANGE: + { + *(sal_Int32 *) pReturn = implRequestChange( *(sal_Int32 *)ppArgs[0], ppException ); + break; + } + default: + OSL_ENSURE( 0 , "unkown method !" ); + } +} + +void SAL_CALL PropertyObject::localGetPropertiesFromRemote( struct Properties *pR ) +{ + OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject ); + + typelib_TypeDescription *pInterfaceType = 0; + getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType ); + + if( !pInterfaceType->bComplete ) + { + typelib_typedescription_complete( &pInterfaceType ); + } + + typelib_TypeDescription *pMethodType = 0; + typelib_typedescriptionreference_getDescription( + &pMethodType, + ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_GET_PROPERTIES] ); + + + uno_Sequence *pResult = 0; + uno_Any exception; + uno_Any *pException = &exception; + urp_sendRequest( m_pEnvRemote, + pMethodType, + oid.pData, + (typelib_InterfaceTypeDescription*) pInterfaceType, + &pResult, + 0, + &pException ); + + if( pException ) + { + OSL_ENSURE( 0 , "remote urp-bridge doesn't support property-object" ); + uno_any_destruct( pException , 0 ); + return; + } + + ProtocolProperty *pP = (ProtocolProperty * ) pResult->elements; + for( sal_Int32 i = 0; i < pResult->nElements ; i ++ ) + { + if( ! assignFromIdlToStruct( pR , pP[i] ) ) + { + OSL_ENSURE( 0 , "unknown property !!!!" ); + } + } + + typelib_typedescription_release( pInterfaceType ); + typelib_typedescription_release( pMethodType ); +} + + +// implementation for call from remote +void SAL_CALL PropertyObject::implGetProperties( uno_Sequence **ppReturnValue ) +{ + typelib_TypeDescription *pElementType= 0; + getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pElementType ); + + OSL_ENSURE( pElementType , "Couldn't get property type" ); + + *ppReturnValue = 0; + uno_sequence_construct( ppReturnValue , pElementType , 0, MAX_PROPERTIES , 0 ); + ProtocolProperty *pElements = (ProtocolProperty * ) ( *ppReturnValue )->elements; + Properties *pP = m_pLocalSetting; + + assignToIdl( &(pElements[PROPERTY_BRIDGEID]),PROPERTY_BRIDGEID, *(Sequence< sal_Int8 > *)&(pP->seqBridgeID) ); + assignToIdl( &(pElements[PROPERTY_TYPECACHESIZE]),PROPERTY_TYPECACHESIZE,pP->nTypeCacheSize ); + assignToIdl( &(pElements[PROPERTY_OIDCACHESIZE]),PROPERTY_OIDCACHESIZE, pP->nOidCacheSize ); + assignToIdl( &(pElements[PROPERTY_TIDCACHESIZE]),PROPERTY_TIDCACHESIZE, pP->nTidCacheSize ); + assignToIdl( &(pElements[PROPERTY_SUPPORTEDVERSIONS]),PROPERTY_SUPPORTEDVERSIONS, pP->sSupportedVersions ); + assignToIdl( &(pElements[PROPERTY_VERSION]),PROPERTY_VERSION, pP->sVersion ); + assignToIdl( &(pElements[PROPERTY_FLUSHBLOCKSIZE]), PROPERTY_FLUSHBLOCKSIZE,pP->nFlushBlockSize ); + assignToIdl( &(pElements[PROPERTY_ONEWAYTIMEOUT_MUSEC]), PROPERTY_ONEWAYTIMEOUT_MUSEC, pP->nOnewayTimeoutMUSEC ); + assignToIdl( &(pElements[PROPERTY_SUPPORTSMUSTREPLY]), PROPERTY_SUPPORTSMUSTREPLY, pP->bSupportsMustReply ); + assignToIdl( &(pElements[PROPERTY_SUPPERTSSYNCHRONOUS]), PROPERTY_SUPPERTSSYNCHRONOUS, pP->bSupportsSynchronous ); + assignToIdl( &(pElements[PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS]), PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS, pP->bSupportsMultipleSynchronous ); + assignToIdl( &(pElements[PROPERTY_CLEARCACHE]), PROPERTY_CLEARCACHE, pP->bClearCache ); + + typelib_typedescription_release( pElementType ); +} + +//---------------------------------------------------------------------------------------------- +sal_Int32 SAL_CALL PropertyObject::localRequestChange( ) +{ + sal_Int32 nResult = 0; + sal_Bool bCall = sal_True; + + // disallow marshaling NOW ! + ClearableMutexGuard marshalingGuard( m_pBridgeImpl->m_marshalingMutex ); + { + MutexGuard guard( m_mutex ); + if( m_bRequestChangeHasBeenCalled || m_bServerWaitingForCommit ) + { + // another transaction is already underway + // try again later ! + bCall = sal_False; + } + m_bRequestChangeHasBeenCalled = sal_True; + + if( bCall ) + { + // calulate random number + rtlRandomPool pool = rtl_random_createPool (); + rtl_random_getBytes( pool , &m_nRandomNumberOfRequest, sizeof( m_nRandomNumberOfRequest ) ); + rtl_random_destroyPool( pool ); + } + } + + if( bCall ) + { + OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject ); + + // gather types for calling + typelib_TypeDescription *pInterfaceType = 0; + getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType ); + + if( !pInterfaceType->bComplete ) + { + typelib_typedescription_complete( &pInterfaceType ); + } + + typelib_TypeDescription *pMethodType = 0; + typelib_typedescriptionreference_getDescription( + &pMethodType, + ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_REQUEST_CHANGE] ); + + void *pArg1 = &m_nRandomNumberOfRequest; + void **ppArgs = &pArg1; + + uno_Any exception; + uno_Any *pException = &exception; + + ClientJob job( m_pEnvRemote, + 0, + m_pBridgeImpl, + oid.pData, + pMethodType, + (typelib_InterfaceTypeDescription*) pInterfaceType, + &nResult, + ppArgs, + &pException ); + + // put the call on the line ! + sal_Bool bSuccess = job.pack(); + + // now allow writing on wire again. + // NOTE : this has been locked, because it is inevitable to set m_bRequestChangeHasBeenCalled + // and call requestChange in an atomar operation. Otherwise, implRequestChange may be called + // inbetween and reply, before the request is put on the wire. This certainly would + // be confusing for the remote counterpart ! + marshalingGuard.clear(); + + // wait for the reply ... + if( bSuccess ) + { + job.wait(); + + if( pException ) + { + // the object is unknown on the other side. + uno_any_destruct( pException , 0 ); + nResult = 0; + } + } + else + { + nResult = 0; + } + typelib_typedescription_release( pInterfaceType ); + typelib_typedescription_release( pMethodType ); + } + + { + MutexGuard guard( m_mutex ); + m_bRequestChangeHasBeenCalled = sal_False; + m_bServerWaitingForCommit = ( 0 == nResult ); + } + return nResult; +} + +// implementation for call from remote +sal_Int32 SAL_CALL PropertyObject::implRequestChange( sal_Int32 nRandomNumber, uno_Any **ppException ) +{ + sal_Int32 nResult = 0; + MutexGuard guard( m_mutex ); + if( m_bRequestChangeHasBeenCalled ) + { + // this side has also called requestChange, now negotiate, which side is allowed + // to commit the change ! + if( m_nRandomNumberOfRequest > nRandomNumber ) + { + // this side may commit !!!! + nResult = 0; + } + else if( m_nRandomNumberOfRequest == nRandomNumber ) + { + // sorry, try again ! + nResult = -1; + } + else if( m_nRandomNumberOfRequest < nRandomNumber ) + { + // the other side may commit ! + nResult = 1; + // m_bServerWaitingForCommit will be set by localRequestChange + } + } + else + { + // This side has NOT called requestChange, so the other side may commit + nResult = 1; + m_bServerWaitingForCommit = sal_True; + } + + *ppException = 0; + return nResult; +} + + + +void SAL_CALL PropertyObject::localCommitChange( const ::rtl::OUString &sProps , sal_Bool *pbExceptionThrown ) +{ + // lock the bridge NOW ! + // NOTE: it is not allowed for other threads to call, when a commit change is underway. + // The remote counterpart cannot if the call following the commit already uses + // the new properties or not. + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + + OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject ); + + osl_resetCondition( m_commitChangeCondition ); + + Properties props = *m_pLocalSetting; + + typelib_TypeDescription *pInterfaceType = 0; + getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType ); + + if( !pInterfaceType->bComplete ) + { + typelib_typedescription_complete( &pInterfaceType ); + } + + typelib_TypeDescription *pMethodType = 0; + typelib_typedescriptionreference_getDescription( + &pMethodType, + ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_COMMIT_CHANGE] ); + +// typelib_TypeDescription *pSequenceType= 0; + + + // extract name/value pairs + uno_Sequence *pSeq = 0; + assignFromStringToPropSeq( sProps, &pSeq ); + assignFromPropSeqToStruct( pSeq , &props ); +// ::std::list< OUString > lst; +// extractTokens( sProps , lst ); + +// getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pSequenceType ); +// uno_sequence_construct( &pSeq , pSequenceType , 0, lst.size() , 0 ); +// ProtocolProperty *pElements = (ProtocolProperty * ) pSeq->elements; + +// sal_Int32 i = 0; +// for( ::std::list< OUString >::iterator ii = lst.begin() ; ii != lst.end() ; ++ ii, i++ ) +// { +// sal_Int32 nAssign = (*ii).indexOf( '=' ); +// if( -1 == nAssign ) +// { +// OString o = OUStringToOString( *ii, RTL_TEXTENCODING_ASCII_US ); +// OSL_ENSURE( !"wrong protocol propertyt format, ignored", o.getStr() ); +// } +// OUString sPropName = (*ii).copy( 0, nAssign ); +// OUString sValue = (*ii).copy( nAssign +1, (*ii).getLength() - nAssign -1 ); + +// sal_Int32 nIndex = getIndexFromString( sPropName ); +// if( -1 == nIndex ) +// { +// OString o = OUStringToOString( sPropName , RTL_TEXTENCODING_ASCII_US); +// OSL_ENSURE( !"unknown protocol property, ignored", o.getStr() ); +// } +// switch( nIndex ) +// { +// // bools +// case PROPERTY_CLEARCACHE: +// { +// sal_Bool bClearCache = (sal_Bool ) sValue.toInt32(); +// assignToIdl( &(pElements[i]) , nIndex , bClearCache ); +// break; +// } +// // ints +// case PROPERTY_TYPECACHESIZE: +// case PROPERTY_OIDCACHESIZE: +// case PROPERTY_TIDCACHESIZE: +// case PROPERTY_FLUSHBLOCKSIZE: +// case PROPERTY_ONEWAYTIMEOUT_MUSEC: +// { +// sal_Int32 nValue = sValue.toInt32(); +// assignToIdl( &(pElements[i]) , nIndex , nValue ); +// break; +// } + +// // strings +// case PROPERTY_VERSION: +// assignToIdl( &(pElements[i]) , nIndex , sValue ); +// break; +// default: +// OString o = OUStringToOString( sPropName, RTL_TEXTENCODING_ASCII_US ); +// OSL_ENSURE( !"readonly protocol property, ignored" , o.getStr() ); +// } +// assignFromIdlToStruct( &props, pElements[i] ); +// } + + void *pArg1 = &pSeq; + uno_Any exception; + uno_Any *pException = &exception; + + ClientJob job( m_pEnvRemote, + 0, + m_pBridgeImpl, + oid.pData, + pMethodType, + (typelib_InterfaceTypeDescription*) pInterfaceType, + 0, + &pArg1, + &pException ); + job.setBridgePropertyCall(); + if( job.pack() ) + { + job.wait(); + } + else + { + OSL_ASSERT( pException != NULL ); + } + + ::uno_type_destructData( + &pSeq, getCppuType( (Sequence< ProtocolProperty > *)0).getTypeLibType(), 0 ); + + *pbExceptionThrown = pException ? sal_True : sal_False; + + if( pException ) + { + OString o = OUStringToOString( ((com::sun::star::uno::Exception*)pException->pData)->Message, + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE( !"exception thrown during calling on PropertyObject",o.getStr() ); + uno_any_destruct( pException , 0 ); + } + else + { + m_pBridgeImpl->applyProtocolChanges( props ); + m_bServerWaitingForCommit = sal_False; + m_bApplyProperties = sal_False; + } + + // let the reader thread go ... + osl_setCondition( m_commitChangeCondition ); + + typelib_typedescription_release( pMethodType ); + typelib_typedescription_release( pInterfaceType ); +} + +void SAL_CALL PropertyObject::implCommitChange( uno_Sequence *pSequence, uno_Any **ppException ) +{ + MutexGuard guard( m_mutex ); + m_propsToBeApplied = *m_pLocalSetting; + + ProtocolProperty *pP = (ProtocolProperty * ) pSequence->elements; + for( sal_Int32 i = 0; i < pSequence->nElements ; i ++ ) + { + if( ! assignFromIdlToStruct( &m_propsToBeApplied , pP[i] ) ) + { + InvalidProtocolChangeException exception; + Type type = getCppuType( &exception ); + exception.Message = OUString::createFromAscii( "urp: unknown Property " ); + exception.Message += pP[i].Name; + exception.invalidProperty = pP[i]; + exception.reason = 1; + + uno_type_any_construct( *ppException, &exception, type.getTypeLibType() , 0 ); + + m_bApplyProperties = sal_False; + m_bServerWaitingForCommit = sal_False; + return; + } + } + + m_bApplyProperties = sal_True; + *ppException = 0; +} + +Properties SAL_CALL PropertyObject::getCommitedChanges() +{ + MutexGuard guard( m_mutex ); + OSL_ASSERT( m_bApplyProperties ); + m_bApplyProperties = sal_False; + m_bServerWaitingForCommit = sal_False; + return m_propsToBeApplied; +} + +void SAL_CALL PropertyObject::waitUntilChangesAreCommitted() +{ + osl_waitCondition( m_commitChangeCondition , 0 ); +} +} diff --git a/bridges/source/remote/urp/urp_propertyobject.hxx b/bridges/source/remote/urp/urp_propertyobject.hxx new file mode 100644 index 000000000000..e6412b0c4ad1 --- /dev/null +++ b/bridges/source/remote/urp/urp_propertyobject.hxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_propertyobject.hxx,v $ + * $Revision: 1.7 $ + * + * 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 <osl/interlck.h> +#include <osl/mutex.hxx> + +#ifndef _OSL_CONDITN_H_ +#include <osl/conditn.h> +#endif +#include <rtl/string.hxx> +#include <uno/sequence2.h> + +#ifndef _BRIDGES_REMOTE_REMOTE_H_ +#include <bridges/remote/remote.h> +#endif +#include "urp_property.hxx" + +namespace bridges_urp { + +struct urp_BridgeImpl; +const sal_Char g_NameOfUrpProtocolPropertiesObject[] = "UrpProtocolProperties"; + +// helper functions +void assignFromStringToStruct( const ::rtl::OUString & sProps , struct Properties *pProps ); + +class PropertyObject : public remote_Interface +{ +private: + ::osl::Mutex m_mutex; + oslCondition m_commitChangeCondition; + oslInterlockedCount m_nRefCount; + urp_BridgeImpl *m_pBridgeImpl; + struct Properties *m_pLocalSetting; + struct Properties m_propsToBeApplied; + + uno_Environment *m_pEnvRemote; + sal_Int32 m_nRandomNumberOfRequest; + sal_Bool m_bRequestChangeHasBeenCalled; + sal_Bool m_bServerWaitingForCommit; + sal_Bool m_bApplyProperties; + +public: + PropertyObject( + struct Properties *pLocalSetting , uno_Environment *pEnvRemote, urp_BridgeImpl *pImpl ); + ~PropertyObject(); + + void SAL_CALL thisAcquire( ) + { + osl_incrementInterlockedCount( &m_nRefCount ); + } + + void SAL_CALL thisRelease() + { + if( ! osl_decrementInterlockedCount( &m_nRefCount ) ) + { + delete this; + } + } + + void SAL_CALL thisDispatch( typelib_TypeDescription const * pMemberType, + void * pReturn, + void * pArgs[], + uno_Any ** ppException ); + +public: // local + sal_Int32 SAL_CALL localRequestChange( ); + void SAL_CALL localCommitChange( const ::rtl::OUString &properties, sal_Bool *pbExceptionThrown ); + void SAL_CALL localGetPropertiesFromRemote( struct Properties * ); + + // returns 0, if nothing was commited. + inline sal_Bool SAL_CALL changesHaveBeenCommited() + { return m_bApplyProperties; } + Properties SAL_CALL getCommitedChanges(); + + void SAL_CALL waitUntilChangesAreCommitted(); + +protected: + // these methods are called by thisDispatch + void SAL_CALL implGetProperties( uno_Sequence **ppReturnValue ); + sal_Int32 SAL_CALL implRequestChange( sal_Int32 nRandomNumber, uno_Any **ppException ); + void SAL_CALL implCommitChange( uno_Sequence *seqOfProperties, uno_Any **ppException ); +}; + +} diff --git a/bridges/source/remote/urp/urp_reader.cxx b/bridges/source/remote/urp/urp_reader.cxx new file mode 100644 index 000000000000..f2ac4f3e9dc7 --- /dev/null +++ b/bridges/source/remote/urp/urp_reader.cxx @@ -0,0 +1,835 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_reader.cxx,v $ + * $Revision: 1.18.20.1 $ + * + * 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/diagnose.h> +#include <rtl/ustrbuf.hxx> + +#include <bridges/remote/connection.h> +#include <bridges/remote/counter.hxx> +#include <bridges/remote/context.h> +#include <bridges/remote/helper.hxx> + +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <uno/environment.h> + +#include "urp_reader.hxx" +#include "urp_writer.hxx" +#include "urp_dispatch.hxx" +#include "urp_job.hxx" +#include "urp_bridgeimpl.hxx" +#include "urp_log.hxx" +#include "urp_propertyobject.hxx" + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; + +#if OSL_DEBUG_LEVEL > 1 +static MyCounter thisCounter( "DEBUG : ReaderThread" ); +#endif + +namespace bridges_urp +{ + + /** + * This callback is used to ensure, that the release call is sent for the correct type. + * + ***/ + void SAL_CALL urp_releaseRemoteCallback ( + remote_Interface *, rtl_uString *pOid, + typelib_TypeDescriptionReference *pTypeRef, uno_Environment *pEnvRemote ) + { + remote_Context *pContext = (remote_Context *) pEnvRemote->pContext; + urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl ); + + pImpl->m_pWriter->insertReleaseRemoteCall( pOid , pTypeRef ); + } + + + struct MessageFlags + { + sal_uInt16 nMethodId; + sal_Bool bRequest; + sal_Bool bType; + sal_Bool bOid; + sal_Bool bTid; + sal_Bool bException; + sal_Bool bMustReply; + sal_Bool bSynchronous; + sal_Bool bMoreFlags; + sal_Bool bIgnoreCache; + sal_Bool bBridgePropertyCall; + ///-------------------------- + inline MessageFlags() + { + bTid = sal_False; + bOid = sal_False; + bType = sal_False; + bException = sal_False; + bMoreFlags = sal_False; + bIgnoreCache = sal_False; + bBridgePropertyCall = sal_False; + } + //--------------------------- + }; // end struct MessageFlags + +inline sal_Bool OReaderThread::getMemberTypeDescription( + typelib_InterfaceAttributeTypeDescription **ppAttributeType, + typelib_InterfaceMethodTypeDescription **ppMethodType, + sal_Bool *pbIsSetter, + sal_uInt16 nMethodId , + typelib_TypeDescriptionReference * pITypeRef ) +{ + if( pITypeRef->eTypeClass != typelib_TypeClass_INTERFACE ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "interface type is not of typeclass interface (" ); + sMessage.append( (sal_Int32) pITypeRef->eTypeClass ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + OSL_ENSURE( 0 , "type is not an interface" ); + return sal_False; + } + + typelib_InterfaceTypeDescription *pInterfaceType = 0; + TYPELIB_DANGER_GET( + (typelib_TypeDescription **)&pInterfaceType , pITypeRef ); + if( ! pInterfaceType ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "No typedescription can be retrieved for type " ); + sMessage.append( OUString( pITypeRef->pTypeName ) ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + OSL_ENSURE( 0 , "urp: unknown type " ); + return sal_False; + } + + if( ! pInterfaceType->aBase.bComplete ) + { + typelib_typedescription_complete( (typelib_TypeDescription **) &pInterfaceType ); + } + + if ( nMethodId >= pInterfaceType->nMapFunctionIndexToMemberIndex ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "vtable out of range for type " ); + sMessage.append( OUString( pITypeRef->pTypeName ) ); + sMessage.appendAscii( " (" ); + sMessage.append( (sal_Int32) nMethodId ); + sMessage.appendAscii( " )" ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + + OSL_ENSURE( 0 , "vtable index out of range" ); + return sal_False; + } + + sal_Int32 nMemberIndex = pInterfaceType->pMapFunctionIndexToMemberIndex[ nMethodId ]; + + if( !( pInterfaceType->nAllMembers > nMemberIndex && nMemberIndex >= 0 ) ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "vtable out of range for type " ); + sMessage.append( OUString( pITypeRef->pTypeName ) ); + sMessage.appendAscii( " (" ); + sMessage.append( (sal_Int32) nMethodId ); + sMessage.appendAscii( " )" ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + + OSL_ENSURE( 0 , "vtable index out of range" ); + return sal_False; + } + + typelib_InterfaceMemberTypeDescription *pMemberType = 0; + typelib_typedescriptionreference_getDescription( + (typelib_TypeDescription **) &pMemberType,pInterfaceType->ppAllMembers[nMemberIndex]); + + if(! pMemberType ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "unknown method type description for type" ); + sMessage.append( OUString( pITypeRef->pTypeName ) ); + sMessage.appendAscii( " (" ); + sMessage.append( (sal_Int32) nMethodId ); + sMessage.appendAscii( " )" ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + + OSL_ENSURE( 0 , "unknown method type description" ); + return sal_False; + } + + if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pMemberType->aBase.eTypeClass ) + { + // Note: pMapMemberIndexToFunctionIndex always contains the function + // index of the attribute getter! setter function index is getter index + // + 1. + *ppAttributeType = (typelib_InterfaceAttributeTypeDescription *) pMemberType; + *pbIsSetter = ! ( + pInterfaceType->pMapMemberIndexToFunctionIndex[nMemberIndex] == nMethodId ); + } + else + { + *ppMethodType = (typelib_InterfaceMethodTypeDescription *) pMemberType; + } + + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType ); + return sal_True; +} + +OReaderThread::OReaderThread( remote_Connection *pConnection, + uno_Environment *pEnvRemote, + OWriterThread * pWriterThread ) : + m_pConnection( pConnection ), + m_pEnvRemote( pEnvRemote ), + m_pWriterThread( pWriterThread ), + m_bDestroyMyself( sal_False ), + m_bContinue( sal_True ), + m_pBridgeImpl((struct urp_BridgeImpl*) + ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl ), + m_unmarshal( m_pBridgeImpl, m_pEnvRemote, ::bridges_remote::remote_createStub ) +{ + m_pEnvRemote->acquireWeak( m_pEnvRemote ); + m_pConnection->acquire( m_pConnection ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + + +OReaderThread::~OReaderThread( ) +{ + m_pEnvRemote->releaseWeak( m_pEnvRemote ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + +// may only be called in the callstack of this thread !!!!! +// run() -> dispose() -> destroyYourself() +void OReaderThread::destroyYourself() +{ + m_bDestroyMyself = sal_True; + m_pConnection->release( m_pConnection ); + m_pConnection = 0; + m_bContinue = sal_False; +} + +void OReaderThread::onTerminated() +{ + if( m_bDestroyMyself ) + { + delete this; + } +} + + +void OReaderThread::disposeEnvironment() +{ + struct remote_Context *pContext = + ( struct remote_Context * ) m_pEnvRemote->pContext; + m_bContinue = sal_False; + if( ! pContext->m_pBridgeImpl->m_bDisposed ) + { + uno_Environment *pEnvRemote = 0; + m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote ); + if( pEnvRemote ) + { + pEnvRemote->dispose( m_pEnvRemote ); + pEnvRemote->release( m_pEnvRemote ); + } + else + { + // environment has been disposed eitherway ! + } + } +} + +inline sal_Bool OReaderThread::readBlock( sal_Int32 *pnMessageCount ) +{ + m_unmarshal.setSize( 8 ); + if( 8 != m_pConnection->read( m_pConnection , m_unmarshal.getBuffer(), 8 ) ) + { + OUString s( RTL_CONSTASCII_USTRINGPARAM( "Unexpected connection closure" ) ); + m_pBridgeImpl->addError( s ); + return sal_False; + } + + sal_Int32 nSize; + m_unmarshal.unpackInt32( &nSize ); + m_unmarshal.unpackInt32( pnMessageCount ); + + if( nSize < 0 ) + { + // buffer too big + // no exception can be thrown, because there is no thread id, which could be + // used. -> terminate ! + OUStringBuffer s; + s.appendAscii( "Packet-size too big (" ); + s.append( (sal_Int64) (sal_uInt32 ) nSize ); + s.append( sal_Unicode( ')' ) ); + m_pBridgeImpl->addError( s.makeStringAndClear() ); + OSL_ENSURE( 0 , "urp bridge: Packet-size too big" ); + return sal_False; + } + + if( 0 == nSize ) + { + // normal termination ! + return sal_False; + } + + // allocate the necessary memory + if( ! m_unmarshal.setSize( nSize ) ) + { + OUStringBuffer s; + s.appendAscii( "Packet-size too big, couln't allocate necessary memory (" ); + s.append( (sal_Int64) (sal_uInt32 ) nSize ); + s.append( sal_Unicode( ')' ) ); + m_pBridgeImpl->addError( s.makeStringAndClear() ); + OSL_ENSURE( 0 , "urp bridge: messages size too large, terminating connection" ); + return sal_False; + } + + sal_Int32 nRead = m_pConnection->read( m_pConnection , m_unmarshal.getBuffer() , nSize ); + + if( nSize != nRead ) + { + OUStringBuffer s; + s.appendAscii( "Unexpected connection closure, inconsistent packet (" ); + s.append( (sal_Int64) (sal_uInt32 ) nSize ); + s.appendAscii( " asked, " ); + s.append( (sal_Int64) (sal_uInt32 ) nRead ); + s.appendAscii( " got )" ); + m_pBridgeImpl->addError( s.makeStringAndClear() ); + // couldn't get the asked amount of bytes, quit + // should only occur, when the environment has already been disposed + OSL_ENSURE( m_pBridgeImpl->m_bDisposed , "urp bridge: inconsistent packet, terminating connection." ); + return sal_False; + } + return sal_True; +} + +inline sal_Bool OReaderThread::readFlags( struct MessageFlags *pFlags ) +{ + sal_uInt8 nBitField; + if( ! m_unmarshal.unpackInt8( &nBitField ) ) + { + m_pBridgeImpl->addError( "Unexpected end of message header (1)" ); + return sal_False; + } + + if( HDRFLAG_LONGHEADER & nBitField ) + { + // this is a long header, interpret the byte as bitfield + pFlags->bTid = (HDRFLAG_NEWTID & nBitField ); + pFlags->bRequest = (HDRFLAG_REQUEST & nBitField); + + if( pFlags->bRequest ) + { + // request + pFlags->bType = ( HDRFLAG_NEWTYPE & nBitField ); + pFlags->bOid = ( HDRFLAG_NEWOID & nBitField ); + pFlags->bIgnoreCache = ( HDRFLAG_IGNORECACHE & nBitField ); + pFlags->bMoreFlags = ( HDRFLAG_MOREFLAGS & nBitField ); + + if( pFlags->bMoreFlags ) + { + // another byte with flags + sal_Int8 moreFlags; + if( ! m_unmarshal.unpackInt8( &moreFlags ) ) + { + m_pBridgeImpl->addError( "Unexpected end of message header (2)" ); + return sal_False; + } + pFlags->bSynchronous = ( HDRFLAG_SYNCHRONOUS & moreFlags ); + pFlags->bMustReply = ( HDRFLAG_MUSTREPLY & moreFlags ); + OSL_ENSURE( (pFlags->bSynchronous && pFlags->bMustReply) || + (!pFlags->bSynchronous && !pFlags->bMustReply), + "urp-bridge : customized calls currently not supported !"); + } + + if( HDRFLAG_LONGMETHODID & nBitField ) + { + // methodid as unsigned short + if( ! m_unmarshal.unpackInt16( &(pFlags->nMethodId )) ) + { + m_pBridgeImpl->addError( "Unexpected end of message header (3)" ); + return sal_False; + } + } + else + { + sal_uInt8 id; + if( ! m_unmarshal.unpackInt8( &id ) ) + { + m_pBridgeImpl->addError( "Unexpected end of message header (4)" ); + return sal_False; + } + pFlags->nMethodId = (sal_uInt16) id; + } + } + else + { + // reply + pFlags->bRequest = sal_False; + pFlags->bException = ( HDRFLAG_EXCEPTION & nBitField ); + } + } + else + { + // short request + pFlags->bRequest = sal_True; + if( 0x40 & nBitField ) + { + sal_uInt8 lower; + if( ! m_unmarshal.unpackInt8( &lower ) ) + { + m_pBridgeImpl->addError( "Unexpected end of message header (5)" ); + return sal_False; + } + pFlags->nMethodId = ( nBitField & 0x3f ) << 8 | lower; + } + else + { + pFlags->nMethodId = ( nBitField & 0x3f ); + } + } + return sal_True; +} + +void OReaderThread::run() +{ + // This vars are needed to hold oid,tid and type information, which should not be cached. + Type lastTypeNoCache; + OUString lastOidNoCache; + ByteSequence lastTidNoCache; + + while( m_bContinue ) + { + sal_Int32 nMessageCount; + if( ! readBlock( &nMessageCount ) ) + { + disposeEnvironment(); + break; + } + + uno_Environment *pEnvRemote = 0; + m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote ); + if( !pEnvRemote ) + { + // environment has been disposed already, quit here + break; + } + ServerMultiJob *pMultiJob = 0; + remote_Interface *pLastRemoteI = 0; + while( ! m_unmarshal.finished() ) + { +#ifdef BRIDGES_URP_PROT + sal_uInt32 nLogStart = m_unmarshal.getPos(); + sal_Bool bIsOneWay = sal_False; + OUString sMemberName; +#endif + MessageFlags flags; + + if( ! readFlags( &flags ) ) + { + m_pBridgeImpl->addError( "incomplete message, skipping block" ); + OSL_ENSURE ( 0 , "urp-bridge : incomplete message, skipping block" ); + break; + } + + // use these ** to access the ids fast ( avoid acquire/release calls ) + sal_Sequence **ppLastTid = flags.bIgnoreCache ? + (sal_Sequence **) &lastTidNoCache : + (sal_Sequence **) &(m_pBridgeImpl->m_lastInTid); + rtl_uString **ppLastOid = flags.bIgnoreCache ? + (rtl_uString ** ) &lastOidNoCache : + (rtl_uString ** ) &(m_pBridgeImpl->m_lastInOid); + typelib_TypeDescriptionReference **ppLastType = + flags.bIgnoreCache ? + (typelib_TypeDescriptionReference ** ) &lastTypeNoCache : + (typelib_TypeDescriptionReference ** ) &(m_pBridgeImpl->m_lastInType); + + // get new type + if( flags.bType ) + { + typelib_TypeDescriptionReference *pTypeRef = 0; + if( m_unmarshal.unpackType( &pTypeRef ) ) + { + // release the old type + typelib_typedescriptionreference_release( *ppLastType ); + // set the new type + *ppLastType = pTypeRef; + + // no release on pTypeRef necessary (will be released by type dtor) + } + else + { + typelib_typedescriptionreference_release( pTypeRef ); + m_pBridgeImpl->addError( "error during unpacking (maybe cached) interface type" ); + OSL_ENSURE( 0 , "urp-bridge : error during unpacking interface type, terminating connection" ); + disposeEnvironment(); + break; + } + if( m_pBridgeImpl->m_lastInType.getTypeClass() != TypeClass_INTERFACE ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "interface type is not of typeclass interface (" ); + sMessage.append( (sal_Int32) m_pBridgeImpl->m_lastInType.getTypeClass() ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + OSL_ENSURE( 0 , "urp-bridge : not an interface type" ); + disposeEnvironment(); + break; + } + } + if( flags.bOid ) + { + rtl_uString *pOid = 0; + if( m_unmarshal.unpackOid( &pOid ) ) + { + rtl_uString_release( *ppLastOid ); + *ppLastOid = pOid; + } + else + { + rtl_uString_release( pOid ); + m_pBridgeImpl->addError( "error during unpacking (maybe cached) oid" ); + OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" ); + disposeEnvironment(); + break; + } + } + + if( flags.bTid ) + { + sal_Sequence *pSeq = 0; + if( m_unmarshal.unpackTid( &pSeq ) ) + { + rtl_byte_sequence_release( *ppLastTid ); + *ppLastTid = pSeq; + } + else + { + rtl_byte_sequence_release( pSeq ); + + m_pBridgeImpl->addError( "error during unpacking (maybe cached) tid" ); + OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" ); + disposeEnvironment(); + break; + } + } + + // do the job + if( flags.bRequest ) + { + bool bHasCc = m_pBridgeImpl->m_properties.bCurrentContext + && flags.nMethodId != REMOTE_RELEASE_METHOD_INDEX + && !rtl::OUString( *ppLastOid ).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + g_NameOfUrpProtocolPropertiesObject ) ); + remote_Interface * pCc = 0; + if ( bHasCc ) + { + typelib_TypeDescription * pType = 0; + TYPELIB_DANGER_GET( + &pType, + XCurrentContext::static_type().getTypeLibType() ); + bool ok = m_unmarshal.unpack( &pCc, pType ); + TYPELIB_DANGER_RELEASE( pType ); + if ( !ok ) + { + OSL_ENSURE( + false, + ("urp_bridge: error while unpacking current" + " context") ); + disposeEnvironment(); + break; + } + } + + //-------------------------- + // handle request + //-------------------------- + // get the membertypedescription + typelib_InterfaceMethodTypeDescription *pMethodType = 0; + typelib_InterfaceAttributeTypeDescription *pAttributeType = 0; + sal_Bool bIsSetter = sal_False; + + if( getMemberTypeDescription( + &pAttributeType, &pMethodType, &bIsSetter, + flags.nMethodId, *ppLastType ) ) + { + if( ! pLastRemoteI || flags.bOid || flags.bType ) + { + // a new interface must be retrieved + + // retrieve the interface NOW from the environment + // (avoid race conditions : oneway followed by release ) + typelib_InterfaceTypeDescription *pInterfaceType = 0; + + TYPELIB_DANGER_GET( + (typelib_TypeDescription ** ) &pInterfaceType , + *ppLastType ); + if( !pInterfaceType ) + { + OUStringBuffer sMessage; + sMessage.appendAscii( "Couldn't retrieve type description for type " ); + sMessage.append( OUString( (*ppLastType)->pTypeName ) ); + m_pBridgeImpl->addError( sMessage.makeStringAndClear() ); + delete pMultiJob; + pMultiJob = 0; + disposeEnvironment(); + pLastRemoteI = 0; // stubs are released during dispose eitherway + break; + } + pEnvRemote->pExtEnv->getRegisteredInterface( + pEnvRemote->pExtEnv, ( void ** ) &pLastRemoteI, + *ppLastOid, pInterfaceType ); + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType ); + + if( !pLastRemoteI && + REMOTE_RELEASE_METHOD_INDEX != flags.nMethodId && + 0 == rtl_ustr_ascii_compare_WithLength( + (*ppLastOid)->buffer, (*ppLastOid)->length, g_NameOfUrpProtocolPropertiesObject ) ) + { + // check for bridge internal propertyobject + pLastRemoteI = m_pBridgeImpl->m_pPropertyObject; + pLastRemoteI->acquire( pLastRemoteI ); + flags.bBridgePropertyCall = sal_True; + } + + // NOTE : Instance provider is called in the executing thread + // Otherwise, instance provider may block the bridge + } + + sal_Bool bCallIsOneway = sal_False; + if( flags.bMoreFlags ) + { + // flags override the default ! + bCallIsOneway = ! flags.bSynchronous; + } + else if( pMethodType && pMethodType->bOneWay ) + { + bCallIsOneway = sal_True; + } + + if( pMultiJob && ! flags.bTid && bCallIsOneway && ! pMultiJob->isFull()) + { + // add to the existing multijob, nothing to do here + } + else + { + // create a new multijob + if( pMultiJob ) + { + // there exists an old one, start it first. + pMultiJob->initiate(); + } + + pMultiJob = new ServerMultiJob( + pEnvRemote, + static_cast< remote_Context * >( + pEnvRemote->pContext ), + *ppLastTid, m_pBridgeImpl, &m_unmarshal, + nMessageCount ); + } + + pMultiJob->setCurrentContext( bHasCc, pCc ); + pMultiJob->setIgnoreCache( flags.bIgnoreCache ); + pMultiJob->setType( *ppLastType ); + if( pMethodType ) + { + pMultiJob->setMethodType( pMethodType , + REMOTE_RELEASE_METHOD_INDEX == flags.nMethodId, + bCallIsOneway ); + } + else if( pAttributeType ) + { + pMultiJob->setAttributeType( pAttributeType, bIsSetter, bCallIsOneway ); + } + else + { + OSL_ASSERT( 0 ); + } + + if( pLastRemoteI ) + pMultiJob->setInterface( pLastRemoteI ); + else + pMultiJob->setOid( *ppLastOid ); + } /* getMemberTypeDescription */ + else + { + delete pMultiJob; + pMultiJob = 0; + pLastRemoteI = 0; // stubs are released during dispose eitherway + disposeEnvironment(); + break; + } +#ifdef BRIDGES_URP_PROT + bIsOneWay = pMethodType && pMethodType->bOneWay; + sMemberName = pMethodType ? + pMethodType->aBase.pMemberName : + pAttributeType->aBase.pMemberName; + sal_uInt32 nLogHeader = m_unmarshal.getPos(); +#endif + if( ! pMultiJob->extract( ) ) + { + // severe error during extracting, dispose + delete pMultiJob; + pMultiJob = 0; + pLastRemoteI = 0; // stubs are released during dispose eitherway + disposeEnvironment(); + break; + } + +#ifdef BRIDGES_URP_PROT + urp_logServingRequest( + m_pBridgeImpl, m_unmarshal.getPos() - nLogStart, + m_unmarshal.getPos() - nLogHeader, + !bIsOneWay, + sMemberName ); +#endif + if ( flags.bBridgePropertyCall ) + { + // call to the bridge internal object. + // these calls MUST be executed within the dispatcher thread in order + // to synchronize properly with protocol changes + // NOTE : Threadid is not preserved for this call. + + // lock the marshaling NOW ! + { + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + + pMultiJob->execute(); + + if( m_pBridgeImpl->m_pPropertyObject->changesHaveBeenCommited() ) + { + Properties props; + props = m_pBridgeImpl->m_pPropertyObject->getCommitedChanges(); + + // This call modified the protocol, apply the changes NOW ! + m_pBridgeImpl->applyProtocolChanges( props ); + } + } + delete pMultiJob; + pMultiJob = 0; + } + } + else + { + //-------------------------- + // handle reply + //-------------------------- + if( pMultiJob ) + { + pMultiJob->initiate(); + pMultiJob = 0; + } + if( pLastRemoteI ) + { + pLastRemoteI->release( pLastRemoteI ); + pLastRemoteI = 0; + } + ClientJob *pClientJob = + m_pBridgeImpl->m_clientJobContainer.remove( *( ByteSequence * )ppLastTid ); + + // Bridge MUST be already disposed, otherwise we got a wrong threadid + // from remote ! + OSL_ASSERT( pClientJob || m_pBridgeImpl->m_bDisposed ); + if( ! pClientJob ) + { + OUStringBuffer error( 128 ); + error.appendAscii( "ThreadID " ); + OString o = byteSequence2HumanReadableString( *(ByteSequence* )ppLastTid ); + error.appendAscii( o.getStr(), o.getLength() ); + error.appendAscii( " unknown, so couldn't unmarshal reply" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + pLastRemoteI = 0; + disposeEnvironment(); + break; + } + + pClientJob->m_bExceptionOccured = flags.bException; + + pClientJob->setUnmarshal( &m_unmarshal ); +#ifdef BRIDGES_URP_PROT + sMemberName = pClientJob->m_pMethodType ? + pClientJob->m_pMethodType->aBase.pMemberName : + pClientJob->m_pAttributeType->aBase.pMemberName; + sal_uInt32 nLogHeader = m_unmarshal.getPos(); +#endif + if( ! pClientJob->extract( ) ) + { + // severe error during extracting, dispose + pLastRemoteI = 0; // stubs are released during dispose eitherway + disposeEnvironment(); + break; + } +#ifdef BRIDGES_URP_PROT + urp_logGettingReply( + m_pBridgeImpl, m_unmarshal.getPos() - nLogStart, + m_unmarshal.getPos() - nLogHeader, sMemberName ); +#endif + sal_Bool bBridgePropertyCallAndWaitingForReply = + pClientJob->isBridgePropertyCall(); + + pClientJob->initiate(); + + if( bBridgePropertyCallAndWaitingForReply ) + { + // NOTE : This must be the reply for commit change. The new properties + // are now applied by the clientJob thread, but the reader thread + // must wait for it, because the next message on the wire already + // uses the new protocol settings. + // waiting for the commit change reply + m_pBridgeImpl->m_pPropertyObject->waitUntilChangesAreCommitted(); + } + } + } // end while( !m_unmarshal.finished() ) + + if( pLastRemoteI ) + pLastRemoteI->release( pLastRemoteI ); + + if( pMultiJob ) + pMultiJob->initiate(); + + if( pEnvRemote ) + pEnvRemote->release( pEnvRemote ); + } + + if( m_pConnection ) + { + m_pConnection->release( m_pConnection ); + m_pConnection = 0; + } +} +} diff --git a/bridges/source/remote/urp/urp_reader.hxx b/bridges/source/remote/urp/urp_reader.hxx new file mode 100644 index 000000000000..9cb36e629c07 --- /dev/null +++ b/bridges/source/remote/urp/urp_reader.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_reader.hxx,v $ + * $Revision: 1.7.20.1 $ + * + * 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 <osl/thread.hxx> + +#include "urp_unmarshal.hxx" + +struct remote_Connection; +typedef struct _uno_Environment uno_Environment; + +namespace bridges_urp +{ + +class OWriterThread; +struct MessageFlags; + +class OReaderThread : + public ::osl::Thread +{ +public: + OReaderThread( remote_Connection *pConnection , + uno_Environment *pEnvRemote, + OWriterThread *pWriterThread ); + ~OReaderThread(); + + // may only be called in the callstack of this thread !!!!! + // run() -> disposeEnvironment() -> dispose() -> destroyYourself() + void destroyYourself(); + +private: + virtual void SAL_CALL run(); + virtual void SAL_CALL onTerminated(); + + inline sal_Bool readBlock( sal_Int32 *pnMessageCount ); + inline sal_Bool readFlags( struct MessageFlags *pFlags ); + + void disposeEnvironment(); + + inline sal_Bool getMemberTypeDescription( + typelib_InterfaceAttributeTypeDescription **ppAttributeType, + typelib_InterfaceMethodTypeDescription **ppMethodType, + sal_Bool *pbIsSetter, + sal_uInt16 nMethodId , + typelib_TypeDescriptionReference *pITypeRef); + + remote_Connection *m_pConnection; + uno_Environment *m_pEnvRemote; + OWriterThread *m_pWriterThread; + sal_Bool m_bDestroyMyself; + sal_Bool m_bContinue; + urp_BridgeImpl *m_pBridgeImpl; + Unmarshal m_unmarshal; +}; + +} diff --git a/bridges/source/remote/urp/urp_replycontainer.hxx b/bridges/source/remote/urp/urp_replycontainer.hxx new file mode 100644 index 000000000000..bcf0394853a4 --- /dev/null +++ b/bridges/source/remote/urp/urp_replycontainer.hxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_replycontainer.hxx,v $ + * $Revision: 1.5 $ + * + * 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 <hash_map> +#include <list> + +#include <osl/mutex.hxx> +#include <osl/diagnose.h> + +#include "urp_threadid.hxx" + +namespace bridges_urp +{ + class ClientJob; + typedef ::std::hash_map< ::rtl::ByteSequence , + ::std::list < ClientJob * > , + HashThreadId , + EqualThreadId > Id2ClientJobStackMap; + + class urp_ClientJobContainer + { + public: + void add( const ::rtl::ByteSequence &id , ClientJob *p ) + { + ::osl::MutexGuard guard( m_mutex ); + m_map[id].push_back( p ); + } + + ClientJob *remove( const ::rtl::ByteSequence & id ) + { + ::osl::MutexGuard guard( m_mutex ); + Id2ClientJobStackMap::iterator ii = m_map.find( id ); + + ClientJob *p = 0; + if( ii != m_map.end() ) + { + p = (*ii).second.back(); + (*ii).second.pop_back(); + if( (*ii).second.empty() ) + { + m_map.erase( ii ); + } + } + + return p; + } + + private: + ::osl::Mutex m_mutex; + Id2ClientJobStackMap m_map; + }; +} diff --git a/bridges/source/remote/urp/urp_threadid.cxx b/bridges/source/remote/urp/urp_threadid.cxx new file mode 100644 index 000000000000..19ede890568c --- /dev/null +++ b/bridges/source/remote/urp/urp_threadid.cxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_threadid.cxx,v $ + * $Revision: 1.4 $ + * + * 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 "urp_threadid.hxx" + +#include <rtl/strbuf.hxx> + +using namespace rtl; + +namespace bridges_urp +{ + rtl::OString byteSequence2HumanReadableString( const rtl::ByteSequence &a ) + { + const sal_uInt8 *p = (const sal_uInt8 * ) a.getConstArray(); + sal_Int32 nLength = a.getLength(); + OStringBuffer buf( a.getLength() * 2 + 2 ); + buf.append( RTL_CONSTASCII_STRINGPARAM( "0x" ) ); + for( sal_Int32 i = 0 ; i < nLength ; i ++ ) + buf.append( (sal_Int32) p[i] , 16 ); + return buf.makeStringAndClear(); + } +} diff --git a/bridges/source/remote/urp/urp_threadid.hxx b/bridges/source/remote/urp/urp_threadid.hxx new file mode 100644 index 000000000000..2fe259b3e89b --- /dev/null +++ b/bridges/source/remote/urp/urp_threadid.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_threadid.hxx,v $ + * $Revision: 1.4 $ + * + * 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 _URP_THREADID_HXX_ +#define _URP_THREADID_HXX_ + +#include <sal/types.h> +#include <rtl/byteseq.hxx> +#include <rtl/string.hxx> + +namespace bridges_urp +{ + + struct EqualThreadId + { + sal_Int32 operator () ( const ::rtl::ByteSequence &a , const ::rtl::ByteSequence &b ) const + { + return a == b; + } + }; + + struct HashThreadId + { + sal_Int32 operator () ( const ::rtl::ByteSequence &a ) const + { + if( a.getLength() >= 4 ) + { + return *(sal_Int32*) a.getConstArray(); + } + return 0; + } + }; + + rtl::OString byteSequence2HumanReadableString( const rtl::ByteSequence &a ); +} +#endif diff --git a/bridges/source/remote/urp/urp_unmarshal.cxx b/bridges/source/remote/urp/urp_unmarshal.cxx new file mode 100644 index 000000000000..798a5ff79ec5 --- /dev/null +++ b/bridges/source/remote/urp/urp_unmarshal.cxx @@ -0,0 +1,710 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_unmarshal.cxx,v $ + * $Revision: 1.16 $ + * + * 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/diagnose.h> + +#include <rtl/alloc.h> +#include <rtl/ustrbuf.hxx> + +#include <uno/data.h> +#include <uno/any2.h> +#include <uno/sequence2.h> + +#include <com/sun/star/uno/Any.hxx> + +#include "urp_unmarshal.hxx" +#include "urp_bridgeimpl.hxx" + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace bridges_urp +{ +static int g_nDetectLittleEndian = 1; +char g_bSystemIsLittleEndian = ((char*)&g_nDetectLittleEndian)[0]; + + +Unmarshal::Unmarshal( struct urp_BridgeImpl *pBridgeImpl, + uno_Environment *pEnvRemote, + remote_createStubFunc callback ) : + m_nBufferSize( 4096 ), + m_base( (sal_Int8*) rtl_allocateMemory( m_nBufferSize ) ), + m_pos( m_base ), + m_nLength( 0 ), + m_callback( callback ), + m_pEnvRemote( pEnvRemote ), + m_pBridgeImpl( pBridgeImpl ) +{ +} + +Unmarshal::~Unmarshal() +{ + rtl_freeMemory( m_base ); +} + +// special unpacks +sal_Bool Unmarshal::unpackTid( sal_Sequence **ppThreadId ) +{ + sal_Int32 nSize; + sal_Bool bReturn = unpackCompressedSize( &nSize ); + if( bReturn ) + { + if( nSize ) + { + rtl_byte_sequence_constructFromArray( ppThreadId , m_pos , nSize ); + m_pos += nSize; + sal_uInt16 nIndex; + bReturn = unpackInt16( &nIndex ); + if( nIndex < m_pBridgeImpl->m_properties.nTidCacheSize ) + { + m_pBridgeImpl->m_pTidIn[nIndex] = *(ByteSequence * )ppThreadId; + } + else if( 0xffff != nIndex ) + { + bReturn = sal_False; + rtl_byte_sequence_construct( ppThreadId , 0 ); + + OUStringBuffer error( 128 ); + error.appendAscii( "cache index for tid " ); + OString o = byteSequence2HumanReadableString( *(ByteSequence * ) ppThreadId ); + error.appendAscii( o.getStr(), o.getLength() ); + error.appendAscii( "out of range(0x"); + error.append( (sal_Int32) nIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + else + { + sal_uInt16 nIndex; + bReturn = unpackInt16( &nIndex ); + if( nIndex < m_pBridgeImpl->m_properties.nTidCacheSize ) + { + *ppThreadId = m_pBridgeImpl->m_pTidIn[nIndex].getHandle(); + rtl_byte_sequence_acquire( *ppThreadId ); + } + else + { + bReturn = sal_False; + rtl_byte_sequence_construct( ppThreadId , 0 ); + OUStringBuffer error(128); + error.appendAscii( "cache index for tids out of range(0x" ); + error.append( (sal_Int32) nIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + } + else + { + m_pBridgeImpl->addError( "couldn't unpack thread id because of previous errors" ); + } + return bReturn; +} + +sal_Bool Unmarshal::unpackOid( rtl_uString **ppOid ) +{ + sal_Bool bReturn = sal_True; + sal_uInt16 nCacheIndex = 0; + + bReturn = bReturn && unpackString( ppOid ); + bReturn = bReturn && unpackInt16( &nCacheIndex ); + + if( bReturn && + ! ( 0xffff == nCacheIndex && 0 == (*ppOid)->length ) /* null reference */ ) + { + if( (*ppOid)->length ) + { + // new unknown reference + if( 0xffff != nCacheIndex ) + { + // oid should be cached ? + if( nCacheIndex < m_pBridgeImpl->m_properties.nOidCacheSize ) + { + m_pBridgeImpl->m_pOidIn[nCacheIndex] = *ppOid; + } + else + { + OUStringBuffer error( 128 ); + error.appendAscii( "new oid provided (" ); + error.append( *ppOid ); + error.appendAscii( "), but new cache index is out of range(0x"); + error.append( (sal_Int32) nCacheIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + + bReturn = sal_False; + rtl_uString_new( ppOid ); + } + } + } + else + { + // reference in cache ! + if( nCacheIndex < m_pBridgeImpl->m_properties.nOidCacheSize ) + { + rtl_uString_assign( ppOid , m_pBridgeImpl->m_pOidIn[nCacheIndex].pData ); + } + else + { + bReturn = sal_False; + rtl_uString_new( ppOid ); + + OUStringBuffer error( 128 ); + error.appendAscii( "cache index for oids out of range(0x"); + error.append( (sal_Int32) nCacheIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + } + + return bReturn; +} + +sal_Bool Unmarshal::unpack( void *pDestination , + typelib_TypeDescription *pTypeDescr ) +{ + // Note: We implement unpack functionality without recursions in order + // to avoid stack overflows caused by rotten URP blocks. + + m_aItemsToUnpack.push( UnpackItem( pDestination, pTypeDescr ) ); + + sal_Bool bReturn = sal_True; + do + { + void * pDest = m_aItemsToUnpack.top().pDest; + typelib_TypeDescription * pType = m_aItemsToUnpack.top().pType; + m_aItemsToUnpack.pop(); + + switch( pType->eTypeClass ) + { + case typelib_TypeClass_VOID: + // do nothing + break; + case typelib_TypeClass_BYTE: + { + bReturn = unpackInt8( pDest ); + break; + } + case typelib_TypeClass_BOOLEAN: + { + bReturn = ! checkOverflow( 1 ); + if( bReturn ) + { + *((sal_Bool*)pDest) = (sal_Bool ) ( *m_pos); + m_pos ++; + } + else + { + *((sal_Bool*)pDest) = 0; + } + break; + } + + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + { + unpackInt16( pDest ); + break; + } + case typelib_TypeClass_ENUM: + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + { + bReturn = unpackInt32( pDest ); + break; + } + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + { + sal_Int8 * p = static_cast< sal_Int8 * >(pDest); + bReturn = ! checkOverflow( 8 ); + if( bReturn ) + { + if( isSystemLittleEndian() ) + { + p[7] = m_pos[0]; + p[6] = m_pos[1]; + p[5] = m_pos[2]; + p[4] = m_pos[3]; + p[3] = m_pos[4]; + p[2] = m_pos[5]; + p[1] = m_pos[6]; + p[0] = m_pos[7]; + } + else + { + p[0] = m_pos[0]; + p[1] = m_pos[1]; + p[2] = m_pos[2]; + p[3] = m_pos[3]; + p[4] = m_pos[4]; + p[5] = m_pos[5]; + p[6] = m_pos[6]; + p[7] = m_pos[7]; + } + m_pos += 8; + } + else + { + // Do not trigger alignment errors: + p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0; + } + break; + } + case typelib_TypeClass_STRING: + { + unpackString( pDest ); + break; + } + case typelib_TypeClass_ANY: + { + uno_Any *pAny = ( uno_Any * )pDest; + + pAny->pType = 0; + // Type is acquired with typelib_typedescription_acquire + + bReturn = unpackType( &(pAny->pType) ); + + typelib_TypeDescription *pDataType = 0; + if( bReturn && pAny->pType ) + { + typelib_typedescriptionreference_getDescription( &pDataType , pAny->pType ); + + if( pDataType ) + { + switch (pDataType->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof(void *) < sizeof(sal_Int64)) + { + pAny->pData = rtl_allocateMemory( sizeof(sal_Int64) ); + } + else + { + pAny->pData = &pAny->pReserved; + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof(void *) < sizeof(float)) + { + pAny->pData = rtl_allocateMemory( sizeof(float) ); + } + else + { + pAny->pData = &pAny->pReserved; + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof(void *) < sizeof(double)) + { + pAny->pData = rtl_allocateMemory( sizeof(double) ); + } + else + { + pAny->pData = &pAny->pReserved; + } + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_UNION: + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_ARRAY: + pAny->pData = rtl_allocateMemory( pDataType->nSize ); + break; + case typelib_TypeClass_ANY: + { + m_pBridgeImpl->addError( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "can't unmarshal any: any in any not supported!" ) ) ); + + pAny->pData = 0; + Type type; // void + pAny->pType = type.getTypeLibType(); + typelib_typedescriptionreference_acquire( pAny->pType ); + + bReturn = sal_False; + break; + } + default: + pAny->pData = &pAny->pReserved; + } + + if ( bReturn ) + { + m_aItemsToUnpack.push( + UnpackItem( pAny->pData, pDataType ) ); + } + } + else + { + OUStringBuffer error; + error.appendAscii( "can't unmarshal any because typedescription for " ); + error.append( pAny->pType->pTypeName ); + error.appendAscii( " is missing" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + + if( pDataType ) + { + typelib_typedescription_release( pDataType ); + } + else + { + pAny->pData = 0; + Type type; // void + pAny->pType = type.getTypeLibType(); + typelib_typedescriptionreference_acquire( pAny->pType ); + + bReturn = sal_False; + } + + break; + } + case typelib_TypeClass_INTERFACE: + { + *(remote_Interface**)pDest = 0; + + rtl_uString *pString = 0; + bReturn = unpackOid( &pString ) && bReturn; + + if( bReturn && pString && pString->length ) + { + m_callback( (remote_Interface**) pDest , + pString, + pType->pWeakRef , + m_pEnvRemote, + urp_releaseRemoteCallback ); + } + if( pString ) + { + rtl_uString_release( pString ); + } + break; + } + case typelib_TypeClass_TYPE: + { + bReturn = unpackType( pDest ); + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_CompoundTypeDescription * pCompType = + (typelib_CompoundTypeDescription *)pType; + + // direct members + typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs; + sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets; + sal_Int32 nDescr = pCompType->nMembers; + + // at least assume 1 byte per member + bReturn = bReturn && ! checkOverflow( nDescr * 1 ); + for ( sal_Int32 nPos = nDescr; nPos; --nPos ) + { + typelib_TypeDescription * pMemberType = 0; + typelib_typedescriptionreference_getDescription( + &pMemberType, ppTypeRefs[ nPos - 1 ] ); + + m_aItemsToUnpack.push( + UnpackItem( (char*)pDest + pMemberOffsets[ nPos - 1 ], + pMemberType, + true /* construct even in error case */ ) ); + + m_aTypesToRelease.push_back( pMemberType ); + } + + // parent + if (pCompType->pBaseTypeDescription) + { + m_aItemsToUnpack.push( + UnpackItem( pDest, + (typelib_TypeDescription *) + pCompType->pBaseTypeDescription ) ); + } + break; + } + case typelib_TypeClass_SEQUENCE: + { + sal_Int32 nLen; + bReturn = unpackCompressedSize( &nLen ); + + // urp protocol does not allow to use the elementsize as a guess, if enough data + // is available. However, at least one byte per member must be within the message + bReturn = bReturn && ! checkOverflow( 1 * nLen ); + uno_Sequence *pSequence = 0; + if( nLen && bReturn ) + { + typelib_TypeDescriptionReference * pETRef = + ((typelib_IndirectTypeDescription *)pType)->pType; + + typelib_TypeDescription * pET = 0; + typelib_typedescriptionreference_getDescription( &pET , pETRef ); + + if( pET ) + { + sal_Int32 nElementSize = pET->nSize; + + pSequence = (uno_Sequence *)rtl_allocateMemory( + SAL_SEQUENCE_HEADER_SIZE + nElementSize * nLen ); + pSequence->nRefCount = 1; + pSequence->nElements = nLen; + + if( typelib_TypeClass_BYTE == pET->eTypeClass ) + { + memcpy( pSequence->elements , m_pos , nLen ); + m_pos += nLen; + } + else + { + for ( sal_Int32 i = nLen; i; --i ) + { + m_aItemsToUnpack.push( + UnpackItem( + ((char*)pSequence->elements) + + (i - 1) * nElementSize, + pET ) ); + } + } + m_aTypesToRelease.push_back( pET ); + } + else + { + bReturn = sal_False; + uno_constructData( &pSequence , pType ); + OUStringBuffer error; + error.appendAscii( "can't unmarshal sequence, because there is no typedescription for element type " ); + error.append( pETRef->pTypeName ); + error.appendAscii( " available" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + else + { + uno_constructData( &pSequence , pType ); + } + + *((uno_Sequence **)pDest) = pSequence; + break; + } + case typelib_TypeClass_UNION: + case typelib_TypeClass_ARRAY: + case typelib_TypeClass_SERVICE: + case typelib_TypeClass_MODULE: + case typelib_TypeClass_INTERFACE_METHOD: + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + case typelib_TypeClass_UNKNOWN: + default: + { + ::rtl::OUStringBuffer buffer( 128 ); + buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Unsupported typeclass during unmarshaling (")); + buffer.append( ( sal_Int32 ) pType->eTypeClass , 10 ); + buffer.appendAscii( ")" ); + m_pBridgeImpl->addError( buffer.makeStringAndClear() ); + bReturn = sal_False; + } + } + + if ( !bReturn ) + { + // construct default data for every remaining item. + while ( !m_aItemsToUnpack.empty() ) + { + const UnpackItem & rItem = m_aItemsToUnpack.top(); + + if ( rItem.bMustBeConstructed ) + uno_constructData( rItem.pDest , rItem.pType ); + + m_aItemsToUnpack.pop(); + } + } + } + while ( !m_aItemsToUnpack.empty() ); + + // release pending type descriptions + TypeDescVector::const_iterator it = m_aTypesToRelease.begin(); + const TypeDescVector::const_iterator end = m_aTypesToRelease.end(); + while ( it != end ) + { + typelib_typedescription_release( *it ); + it++; + } + m_aTypesToRelease.clear(); + + return bReturn; +} + +sal_Bool Unmarshal::unpackType( void *pDest ) +{ + *(typelib_TypeDescriptionReference **) pDest = 0; + + sal_uInt8 nTypeClass; + sal_Bool bReturn = unpackInt8( &nTypeClass ); + + typelib_TypeDescriptionReference *pTypeRef = 0; + if( bReturn ) + { + if( nTypeClass <= 14 /* any */ ) + { + pTypeRef = * typelib_static_type_getByTypeClass((typelib_TypeClass )nTypeClass); + typelib_typedescriptionreference_acquire( pTypeRef ); + } + else + { + sal_uInt16 nCacheIndex = 0; + bReturn = bReturn && unpackInt16( &nCacheIndex ); + + if( bReturn ) + { + if( nTypeClass & 0x80 ) + { + // new type + rtl_uString *pString = 0; + bReturn = bReturn && unpackString( &pString ); + if( bReturn ) + { + typelib_TypeDescription *pType = 0; + typelib_typedescription_getByName( &pType, pString ); + if( pType ) + { + // type is known in this process + if( (typelib_TypeClass )(nTypeClass & 0x7f) == pType->eTypeClass ) + { + //typename and typeclass match, this is as it should be + pTypeRef = pType->pWeakRef; + typelib_typedescriptionreference_acquire( pTypeRef ); + } + else + { + // typename and typeclass do not match, dispose the bridge + // as there must be inconsistent type base between both processes + // or trash comes over the wire ... + bReturn = sal_False; + OUStringBuffer error( 128 ); + error.appendAscii( "it is tried to introduce type " ); + error.append( pString ); + error.appendAscii( "with typeclass " ); + error.append( (sal_Int32)( nTypeClass & 0x7f ) , 10 ); + error.appendAscii( " , which does not match with typeclass " ); + error.append( (sal_Int32) pType->eTypeClass ,10 ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + typelib_typedescription_release( pType ); + pType = 0; + } + else + { + // a type by this name is not known in the process. + if( (nTypeClass & 0x7f) < typelib_TypeClass_UNKNOWN ) + { + // typeclass is within a valid range, introduce the new + // type. + typelib_typedescriptionreference_new( + &pTypeRef, (typelib_TypeClass )(nTypeClass & 0x7f), pString ); + } + else + { + // typeclass is out of range ! + bReturn = sal_False; + OUStringBuffer error( 128 ); + error.appendAscii( "it is tried to introduce type " ); + error.append( pString ); + error.appendAscii( "with an out of range typeclass " ); + error.append( (sal_Int32)( nTypeClass & 0x7f ) , 10 ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + + if( bReturn && nCacheIndex != 0xffff ) + { + if( nCacheIndex < m_pBridgeImpl->m_properties.nTypeCacheSize ) + { + m_pBridgeImpl->m_pTypeIn[nCacheIndex] = *( Type * )&pTypeRef; + } + else + { + bReturn = sal_False; + OUStringBuffer error( 128 ); + error.appendAscii( "cache index for type " ); + error.append( pString ); + error.appendAscii( "out of range(0x" ); + error.append( (sal_Int32) nCacheIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + } + if( pString ) + { + rtl_uString_release( pString ); + } + } + else + { + if( nCacheIndex < m_pBridgeImpl->m_properties.nTypeCacheSize ) + { + pTypeRef = m_pBridgeImpl->m_pTypeIn[nCacheIndex].getTypeLibType(); + typelib_typedescriptionreference_acquire( pTypeRef ); + } + else + { + bReturn = sal_False; + OUStringBuffer error; + error.appendAscii( "cache index for types out of range(0x" ); + error.append( (sal_Int32) nCacheIndex ,16 ); + error.appendAscii( ")" ); + m_pBridgeImpl->addError( error.makeStringAndClear() ); + } + } + } + } + } + if( ! pTypeRef ) + { + pTypeRef = * typelib_static_type_getByTypeClass(typelib_TypeClass_VOID); + typelib_typedescriptionreference_acquire( pTypeRef ); + } + // pTypeRef is already acquired + *(typelib_TypeDescriptionReference**)pDest = pTypeRef; + return bReturn; +} + +} + diff --git a/bridges/source/remote/urp/urp_unmarshal.hxx b/bridges/source/remote/urp/urp_unmarshal.hxx new file mode 100644 index 000000000000..f8590c20d89d --- /dev/null +++ b/bridges/source/remote/urp/urp_unmarshal.hxx @@ -0,0 +1,283 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_unmarshal.hxx,v $ + * $Revision: 1.9 $ + * + * 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 _URP_UNMARSHAL_HXX_ +#define _URP_UNMARSHAL_HXX_ + +#include <stack> +#include <vector> +#include <rtl/byteseq.hxx> +#include <rtl/ustrbuf.hxx> +#include <bridges/remote/context.h> + +#ifndef _BRIDGES_REMOTE_HELPER_HXX_ +#include <bridges/remote/helper.hxx> +#endif +#include <com/sun/star/uno/Type.hxx> +#include "urp_bridgeimpl.hxx" + +typedef struct _uno_Environment uno_Environment; +struct remote_Interface; + +namespace bridges_urp +{ + +extern char g_bSystemIsLittleEndian; +class ThreadId; +struct urp_BridgeImpl; +void SAL_CALL urp_releaseRemoteCallback( + remote_Interface *pRemoteI,rtl_uString *pOid, + typelib_TypeDescriptionReference *pTypeRef, + uno_Environment *pEnvRemote ); + +struct UnpackItem +{ + void * pDest; + typelib_TypeDescription * pType; + bool bMustBeConstructed; + + UnpackItem() + : pDest( 0 ), pType( 0 ), bMustBeConstructed( false ) {} + UnpackItem( void * d, typelib_TypeDescription * t, bool b = false ) + : pDest( d ), pType( t ), bMustBeConstructed( b ) {} +}; + +typedef std::stack< UnpackItem > UnpackItemStack; +typedef std::vector< typelib_TypeDescription * > TypeDescVector; + +class Unmarshal +{ +public: + Unmarshal( + struct urp_BridgeImpl *, + uno_Environment *pEnvRemote, + remote_createStubFunc callback ); + ~Unmarshal(); + + inline sal_Bool finished() + { return m_base + m_nLength == m_pos; } + inline sal_uInt32 getPos() + { return (sal_uInt32 ) (m_pos - m_base); } + + inline sal_Bool setSize( sal_Int32 nSize ); + + sal_Bool unpack( void *pDest, typelib_TypeDescription *pType ); + inline sal_Bool unpackCompressedSize( sal_Int32 *pData ); + inline sal_Bool unpackInt8( void *pDest ); + inline sal_Bool unpackString( void *pDest ); + inline sal_Bool unpackInt16( void *pDest ); + inline sal_Bool unpackInt32( void *pDest ); + sal_Bool unpackType( void *pDest ); + + inline sal_Bool unpackAny( void *pDest ); + sal_Bool unpackOid( rtl_uString **ppOid ); + sal_Bool unpackTid( sal_Sequence **ppThreadId ); + + sal_Int8 *getBuffer() + { return m_base; } + inline sal_Bool isSystemLittleEndian() + { return g_bSystemIsLittleEndian; } + +private: + inline sal_Bool checkOverflow( sal_Int32 nNextMem ); + + UnpackItemStack m_aItemsToUnpack; + TypeDescVector m_aTypesToRelease; + + sal_Int32 m_nBufferSize; + sal_Int8 *m_base; + sal_Int8 *m_pos; + sal_Int32 m_nLength; + + remote_createStubFunc m_callback; + uno_Environment *m_pEnvRemote; + urp_BridgeImpl *m_pBridgeImpl; +}; + +inline sal_Bool Unmarshal::setSize( sal_Int32 nSize ) +{ + if( nSize > m_nBufferSize ) + { + // adjust buffer size and length. + sal_Int8 * base = + (sal_Int8*)rtl_reallocateMemory (m_base, sal_Size(nSize)); + if (base != 0) + { + m_base = base; + m_nLength = m_nBufferSize = nSize; + } + } + else + { + // adjust buffer length, only. + m_nLength = nSize; + } + + // reset buffer position, and leave. + m_pos = m_base; + return (m_nLength == nSize); +} + +inline sal_Bool Unmarshal::checkOverflow( sal_Int32 nNextMem ) +{ + sal_Bool bOverflow = nNextMem < 0 || + (((sal_Int32)( m_pos - m_base )) + nNextMem ) > m_nLength; + if( bOverflow ) + m_pBridgeImpl->addError( "message too short" ); + return bOverflow; +} + + +inline sal_Bool Unmarshal::unpackInt8( void *pDest ) +{ + sal_Bool bReturn = ! checkOverflow( 1 ); + if( bReturn ) + { + *((sal_Int8*)pDest ) = *m_pos; + m_pos++; + } + else + { + *((sal_Int8*)pDest ) = 0; + } + return bReturn; +} + +inline sal_Bool Unmarshal::unpackInt32( void *pDest ) +{ + sal_uInt32 *p = ( sal_uInt32 * ) pDest; + sal_Bool bReturn = ! checkOverflow(4); + if( bReturn ) + { + if( isSystemLittleEndian() ) + { + ((sal_Int8*) p )[3] = m_pos[0]; + ((sal_Int8*) p )[2] = m_pos[1]; + ((sal_Int8*) p )[1] = m_pos[2]; + ((sal_Int8*) p )[0] = m_pos[3]; + } + else + { + ((sal_Int8*) p )[3] = m_pos[3]; + ((sal_Int8*) p )[2] = m_pos[2]; + ((sal_Int8*) p )[1] = m_pos[1]; + ((sal_Int8*) p )[0] = m_pos[0]; + } + m_pos += 4; + } + else + { + *p = 0; + } + return bReturn; +} + +inline sal_Bool Unmarshal::unpackInt16( void *pDest ) +{ + sal_uInt16 *p = ( sal_uInt16 * ) pDest; + + sal_Bool bReturn = ! checkOverflow( 2 ); + if( bReturn ) + { + if( isSystemLittleEndian() ) + { + ((sal_Int8*) p )[1] = m_pos[0]; + ((sal_Int8*) p )[0] = m_pos[1]; + } + else + { + ((sal_Int8*) p )[1] = m_pos[1]; + ((sal_Int8*) p )[0] = m_pos[0]; + } + m_pos ++; + m_pos ++; + } + else + { + *p = 0; + } + return bReturn; +} + +inline sal_Bool Unmarshal::unpackString( void *pDest ) +{ + sal_Int32 nLength; + sal_Bool bReturn = unpackCompressedSize( &nLength ); + + bReturn = bReturn && ! checkOverflow( nLength ); + if( bReturn ) + { + *(rtl_uString **) pDest = 0; + rtl_string2UString( (rtl_uString**) pDest, (const sal_Char * )m_pos , nLength, + RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS ); + m_pos += nLength; + } + else + { + *(rtl_uString ** ) pDest = 0; + rtl_uString_new( (rtl_uString **) pDest ); + } + return bReturn; +} + +inline sal_Bool Unmarshal::unpackCompressedSize( sal_Int32 *pData ) +{ + sal_uInt8 n8Size; + sal_Bool bReturn = unpackInt8( &n8Size ); + if( bReturn ) + { + if( n8Size == 0xff ) + { + unpackInt32( pData ); + } + else + { + *pData = (sal_Int32 ) n8Size; + } + } + return bReturn; +} + +inline sal_Bool Unmarshal::unpackAny( void *pDest ) +{ + typelib_TypeDescriptionReference *pTypeRef = + * typelib_static_type_getByTypeClass( typelib_TypeClass_ANY ); + + typelib_TypeDescription * pTD = 0; + typelib_typedescriptionreference_getDescription( &pTD, pTypeRef ); + + sal_Bool bReturn = unpack( pDest, pTD ); + + typelib_typedescription_release( pTD ); + + return bReturn; +} + +} +#endif diff --git a/bridges/source/remote/urp/urp_writer.cxx b/bridges/source/remote/urp/urp_writer.cxx new file mode 100644 index 000000000000..248be6c37098 --- /dev/null +++ b/bridges/source/remote/urp/urp_writer.cxx @@ -0,0 +1,272 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_writer.cxx,v $ + * $Revision: 1.17.20.1 $ + * + * 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 <osl/time.h> + +#include <osl/mutex.hxx> +#include <osl/conditn.h> + +#include <typelib/typedescription.h> + +#include <bridges/remote/connection.h> +#include <bridges/remote/remote.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +#include <bridges/remote/counter.hxx> + +#include "urp_writer.hxx" +#include "urp_bridgeimpl.hxx" +#include "urp_marshal.hxx" +#include "urp_dispatch.hxx" + +#if OSL_DEBUG_LEVEL > 1 +static MyCounter thisCounter( "DEBUG : WriterThread" ); +#endif + +using namespace ::osl; + +namespace bridges_urp { + +OWriterThread::OWriterThread( remote_Connection *pConnection, urp_BridgeImpl *pBridgeImpl, + uno_Environment *pEnvRemote) : + m_bAbort( sal_False ), + m_bInBlockingWait( sal_False ), + m_bEnterBlockingWait( sal_False ), + m_pConnection( pConnection ), + m_pBridgeImpl( pBridgeImpl ), + m_pEnvRemote( pEnvRemote ) + +{ + m_oslCondition = osl_createCondition(); + osl_resetCondition( m_oslCondition ); + m_pConnection->acquire( m_pConnection ); + +#if OSL_DEBUG_LEVEL > 1 + thisCounter.acquire(); +#endif +} + +OWriterThread::~OWriterThread() +{ + osl_destroyCondition( m_oslCondition ); + m_pConnection->release( m_pConnection ); +#if OSL_DEBUG_LEVEL > 1 + thisCounter.release(); +#endif +} + + +// touch is called with locked m_marshalingMutex +void OWriterThread::touch( sal_Bool bImmediately ) +{ + if( bImmediately || m_pBridgeImpl->m_blockMarshaler.getPos() > m_pBridgeImpl->m_properties.nFlushBlockSize ) + { + write(); + } + else + { + // wake the writer thread up + if( m_bInBlockingWait ) + { + m_bInBlockingWait = sal_False; + osl_setCondition( m_oslCondition ); + } + else + { + // ensure, that the writing thread does not enter blocking mode + m_bEnterBlockingWait = sal_False; + } + } +} + + +void OWriterThread::abortThread() +{ + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + + m_bAbort = sal_True; + m_bEnterBlockingWait = sal_False; + if( m_bInBlockingWait ) + { + m_bInBlockingWait = sal_False; + osl_setCondition( m_oslCondition ); + } +} + + +// must be called with locked marshaling mutex +void OWriterThread::write() +{ + if( ! m_pBridgeImpl->m_blockMarshaler.empty() && ! m_bAbort ) + { + m_pBridgeImpl->m_blockMarshaler.finish( m_pBridgeImpl->m_nMarshaledMessages); + m_pBridgeImpl->m_nMarshaledMessages = 0; + + sal_Int32 nLength = m_pBridgeImpl->m_blockMarshaler.getSize(); + sal_Int8 *pBuf = m_pBridgeImpl->m_blockMarshaler.getBuffer(); + + if( nLength != m_pConnection->write( m_pConnection, pBuf, nLength )) + { + m_pBridgeImpl->m_blockMarshaler.restart(); + return; + } + m_pConnection->flush( m_pConnection ); + m_pBridgeImpl->m_blockMarshaler.restart(); + } +} + +void OWriterThread::sendEmptyMessage() +{ + // must be called with locked marshaling mutex + sal_Int32 a[2] = {0,0}; + m_pConnection->write( m_pConnection , (sal_Int8*) a , sizeof( sal_Int32) *2 ); +} + +void OWriterThread::insertReleaseRemoteCall( + rtl_uString *pOid,typelib_TypeDescriptionReference *pTypeRef) +{ + { + ::osl::MutexGuard guard( m_releaseCallMutex ); + + struct RemoteReleaseCall call; + call.sOid = pOid; + call.typeInterface = pTypeRef; + m_lstReleaseCalls.push_back( call ); + } + { + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + if( m_bInBlockingWait ) + { + m_bInBlockingWait = sal_False; + osl_setCondition( m_oslCondition ); + } + else + { + // ensure, that the writing thread does not enter blocking mode + m_bEnterBlockingWait = sal_False; + } + } +} + +/* The release calls for doubled interfaces + * + * + ***/ +void OWriterThread::executeReleaseRemoteCalls() +{ + ::std::list< struct RemoteReleaseCall > lstReleaseCalls; + { + ::osl::MutexGuard guard( m_releaseCallMutex ); + lstReleaseCalls.swap( m_lstReleaseCalls ); + } + + for( ::std::list< struct RemoteReleaseCall >::iterator ii = lstReleaseCalls.begin(); + ii != lstReleaseCalls.end(); + ++ ii ) + { + struct RemoteReleaseCall &call = (*ii) ; + + typelib_TypeDescription *pInterfaceTypeDesc = 0; + typelib_TypeDescription *pReleaseMethod = 0; + + call.typeInterface.getDescription( &pInterfaceTypeDesc ); + if( ! pInterfaceTypeDesc->bComplete ) + { + typelib_typedescription_complete( &pInterfaceTypeDesc ); + } + + uno_Any any; + uno_Any *pAny = &any; + + typelib_typedescriptionreference_getDescription( + &pReleaseMethod , + ((typelib_InterfaceTypeDescription*)pInterfaceTypeDesc)->ppAllMembers[REMOTE_RELEASE_METHOD_INDEX] ); + + urp_sendRequest_internal( + m_pEnvRemote , pReleaseMethod, call.sOid.pData, + (typelib_InterfaceTypeDescription*) pInterfaceTypeDesc, 0, 0, + &pAny ); + + typelib_typedescription_release( pReleaseMethod ); + typelib_typedescription_release( pInterfaceTypeDesc ); + } +} + + +void OWriterThread::run() +{ + while( ! m_bAbort ) + { + sal_Bool bWait; + { + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + bWait = m_bEnterBlockingWait; + if( bWait ) + { + osl_resetCondition( m_oslCondition ); + m_bInBlockingWait = sal_True; + } + m_bEnterBlockingWait = sal_True; + } + + // wait for some notification + if( bWait ) + osl_waitCondition( m_oslCondition , 0 ); + // (m_bInBlockingWait = sal_False was set by the activating thread) + + if( m_bAbort ) + break; + + // Wait for the timeout + TimeValue value = { 0 , 1000 * m_pBridgeImpl->m_properties.nOnewayTimeoutMUSEC }; + osl_resetCondition( m_oslCondition ); + osl_waitCondition( m_oslCondition , &value ); + + // check if there are some release calls to be sent .... + executeReleaseRemoteCalls(); + + { + // write to the socket + MutexGuard guard( m_pBridgeImpl->m_marshalingMutex ); + if( ! m_pBridgeImpl->m_blockMarshaler.empty() ) + { + write(); + } + } + } +} + + +} + diff --git a/bridges/source/remote/urp/urp_writer.hxx b/bridges/source/remote/urp/urp_writer.hxx new file mode 100644 index 000000000000..f5cafe261280 --- /dev/null +++ b/bridges/source/remote/urp/urp_writer.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: urp_writer.hxx,v $ + * $Revision: 1.7.20.1 $ + * + * 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 <list> + +#include <osl/conditn.h> +#include <osl/mutex.hxx> + +#include <rtl/ustring.hxx> + +#include <osl/thread.hxx> + +#include <com/sun/star/uno/Type.hxx> + +struct remote_Connection; + +namespace bridges_urp +{ + struct RemoteReleaseCall + { + ::rtl::OUString sOid; + ::com::sun::star::uno::Type typeInterface; + }; + + struct urp_BridgeImpl; + class OWriterThread : + public ::osl::Thread + { + public: + OWriterThread( remote_Connection *pConnection, + urp_BridgeImpl *m_pBridgeImpl, + uno_Environment *pEnvRemote); + ~OWriterThread( ); + + virtual void SAL_CALL run(); + + void touch( sal_Bool bImmediately ); + void sendEmptyMessage(); + + void abortThread(); + + void SAL_CALL insertReleaseRemoteCall ( + rtl_uString *pOid,typelib_TypeDescriptionReference *pTypeRef); + void SAL_CALL executeReleaseRemoteCalls(); + + private: + void write(); + oslCondition m_oslCondition; + sal_Bool m_bAbort; + sal_Bool m_bInBlockingWait; + sal_Bool m_bEnterBlockingWait; + remote_Connection *m_pConnection; + urp_BridgeImpl *m_pBridgeImpl; + uno_Environment *m_pEnvRemote; // this is held weak only + + ::osl::Mutex m_releaseCallMutex; + ::std::list< struct RemoteReleaseCall > m_lstReleaseCalls; + }; +} + 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..5e2c5e7859c8 --- /dev/null +++ b/bridges/test/com/sun/star/lib/TestBed.java @@ -0,0 +1,235 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestBed.java,v $ + * $Revision: 1.7 $ + * + * 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..b9072ba436d2 --- /dev/null +++ b/bridges/test/com/sun/star/lib/makefile.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.4 $ +# +# 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..2c7e314afc82 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug107753_Test.java @@ -0,0 +1,397 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug107753_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..0585e1c8f650 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug108825_Test.java @@ -0,0 +1,166 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug108825_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..1a537895b0ed --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug110892_Test.java @@ -0,0 +1,127 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug110892_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..40eccdba2cc6 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug111153_Test.java @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug111153_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..fdcd993bb94a --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug114133_Test.java @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug114133_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..247bf65ba185 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug51323_Test.java @@ -0,0 +1,87 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug51323_Test.java,v $ + * $Revision: 1.3 $ + * + * 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..13b61447c320 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug92174_Test.java @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug92174_Test.java,v $ + * $Revision: 1.7 $ + * + * 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..2fdd457f0dcb --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug97697_Test.java @@ -0,0 +1,108 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug97697_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..86232e664c93 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug98508_Test.idl,v $ + * $Revision: 1.4 $ + * + * 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..79e373014c4a --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/Bug98508_Test.java @@ -0,0 +1,107 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Bug98508_Test.java,v $ + * $Revision: 1.6 $ + * + * 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..407164c66c7f --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/MethodIdTest.java @@ -0,0 +1,476 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: MethodIdTest.java,v $ + * $Revision: 1.6 $ + * + * 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..f42bca060a02 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.idl @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: PolyStructTest.idl,v $ + * $Revision: 1.5 $ + * + * 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..1c9e387ddb32 --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/PolyStructTest.java @@ -0,0 +1,263 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: PolyStructTest.java,v $ + * $Revision: 1.6 $ + * + * 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..37fb8ffee05b --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/StopMessageDispatcherTest.java @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: StopMessageDispatcherTest.java,v $ + * $Revision: 1.5 $ + * + * 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..b049237c7a6e --- /dev/null +++ b/bridges/test/com/sun/star/lib/uno/bridges/java_remote/makefile.mk @@ -0,0 +1,55 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.11 $ +# +# 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..7617e994d729 --- /dev/null +++ b/bridges/test/inter_libs_exc/inter.cxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: inter.cxx,v $ + * $Revision: 1.3 $ + * + * 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; +} diff --git a/bridges/test/inter_libs_exc/makefile.mk b/bridges/test/inter_libs_exc/makefile.mk new file mode 100644 index 000000000000..692322435b24 --- /dev/null +++ b/bridges/test/inter_libs_exc/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# 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..28c4dfd5bb15 --- /dev/null +++ b/bridges/test/inter_libs_exc/share.h @@ -0,0 +1,7 @@ + +#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)(); diff --git a/bridges/test/inter_libs_exc/starter.cxx b/bridges/test/inter_libs_exc/starter.cxx new file mode 100644 index 000000000000..9c3117f82a9c --- /dev/null +++ b/bridges/test/inter_libs_exc/starter.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: starter.cxx,v $ + * $Revision: 1.3 $ + * + * 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" ); + } +} 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..9390c66fc467 --- /dev/null +++ b/bridges/test/inter_libs_exc/thrower.cxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: thrower.cxx,v $ + * $Revision: 1.3 $ + * + * 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; +} 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..e219b3adbf72 --- /dev/null +++ b/bridges/test/java_uno/acquire/TestAcquire.java @@ -0,0 +1,307 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestAcquire.java,v $ + * $Revision: 1.6 $ + * + * 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..d027c067dad7 --- /dev/null +++ b/bridges/test/java_uno/acquire/makefile.mk @@ -0,0 +1,121 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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 = testacquire.map +SHL1IMPLIB = itestacquire + +JAVAFILES = TestAcquire.java +JARFILES = OOoRunner.jar juh.jar jurt.jar ridl.jar + +.INCLUDE: target.mk + +ALLTAR: \ + $(BIN)$/testacquire-java-client$(SCRIPTEXT) \ + $(BIN)$/testacquire-java-server$(SCRIPTEXT) \ + $(BIN)$/testacquire-native-client$(SCRIPTEXT) \ + $(BIN)$/testacquire-native-server$(SCRIPTEXT) + +.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$(SCRIPTEXT): + 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$(SCRIPTEXT): + 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$(SCRIPTEXT): + 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$(SCRIPTEXT): + 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..332b143b5450 --- /dev/null +++ b/bridges/test/java_uno/acquire/testacquire.cxx @@ -0,0 +1,577 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testacquire.cxx,v $ + * $Revision: 1.7 $ + * + * 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) { + throw "osl::Condition::wait failed"; + } +} + +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::createFromAscii( + "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::createFromAscii( + "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" void SAL_CALL component_getImplementationEnvironment( + char const ** envTypeName, uno_Environment **) +{ + if (envTypeName != 0) { + *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } +} + +extern "C" 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::OUString::createFromAscii("/")); + keyName += implementationName; + keyName += rtl::OUString::createFromAscii("/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()); +} diff --git a/bridges/test/java_uno/acquire/testacquire.map b/bridges/test/java_uno/acquire/testacquire.map new file mode 100644 index 000000000000..227274db922d --- /dev/null +++ b/bridges/test/java_uno/acquire/testacquire.map @@ -0,0 +1,8 @@ +UDK_3.1 { + global: + component_getFactory; + component_getImplementationEnvironment; + component_writeInfo; + local: + *; +}; diff --git a/bridges/test/java_uno/acquire/types.idl b/bridges/test/java_uno/acquire/types.idl new file mode 100644 index 000000000000..8eba8d374fdd --- /dev/null +++ b/bridges/test/java_uno/acquire/types.idl @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.idl,v $ + * $Revision: 1.5 $ + * + * 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..ec9ac5fb4162 --- /dev/null +++ b/bridges/test/java_uno/any/TestAny.java @@ -0,0 +1,2270 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestAny.java,v $ + * $Revision: 1.5.20.1 $ + * + * 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..2b53163a087e --- /dev/null +++ b/bridges/test/java_uno/any/TestJni.java @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestJni.java,v $ + * $Revision: 1.5 $ + * + * 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..ec533054579d --- /dev/null +++ b/bridges/test/java_uno/any/TestRemote.java @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestRemote.java,v $ + * $Revision: 1.8 $ + * + * 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..1957194f856a --- /dev/null +++ b/bridges/test/java_uno/any/makefile.mk @@ -0,0 +1,131 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.11 $ +# +# 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$(SCRIPTEXT) \ + $(OUT)$/bin$/TestJni$(SCRIPTEXT) + +$(OUT)$/bin$/TestRemote$(SCRIPTEXT) : $(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$(SCRIPTEXT) : $(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..4959db8fccc8 --- /dev/null +++ b/bridges/test/java_uno/any/test_javauno_any.map @@ -0,0 +1,6 @@ +UDK_3.1 { + 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..ce64a843130c --- /dev/null +++ b/bridges/test/java_uno/any/transport.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: transport.cxx,v $ + * $Revision: 1.6 $ + * + * 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; +} diff --git a/bridges/test/java_uno/any/types.idl b/bridges/test/java_uno/any/types.idl new file mode 100644 index 000000000000..18827b3d46df --- /dev/null +++ b/bridges/test/java_uno/any/types.idl @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.idl,v $ + * $Revision: 1.4 $ + * + * 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..38c9500629e3 --- /dev/null +++ b/bridges/test/java_uno/equals/TestEquals.java @@ -0,0 +1,1307 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: TestEquals.java,v $ + * $Revision: 1.9 $ + * + * 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).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..4064b5e48f09 --- /dev/null +++ b/bridges/test/java_uno/equals/makefile.mk @@ -0,0 +1,100 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# 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 = testequals.map +SHL1IMPLIB = itestequals + +JAVAFILES = TestEquals.java +JARFILES = juh.jar jurt.jar ridl.jar + +.INCLUDE: target.mk + +ALLTAR: $(BIN)$/testequals$(SCRIPTEXT) + +.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$(SCRIPTEXT): $(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..32911bff9c7d --- /dev/null +++ b/bridges/test/java_uno/equals/testequals.cxx @@ -0,0 +1,235 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testequals.cxx,v $ + * $Revision: 1.6 $ + * + * 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::createFromAscii("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::createFromAscii( + "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" void SAL_CALL component_getImplementationEnvironment( + sal_Char const ** pEnvTypeName, uno_Environment **) +{ + *pEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" 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::OUString::createFromAscii("/")); + aKeyName += rtl::OUString::createFromAscii(pImplementationName); + aKeyName += rtl::OUString::createFromAscii("/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()); +} diff --git a/bridges/test/java_uno/equals/testequals.map b/bridges/test/java_uno/equals/testequals.map new file mode 100644 index 000000000000..227274db922d --- /dev/null +++ b/bridges/test/java_uno/equals/testequals.map @@ -0,0 +1,8 @@ +UDK_3.1 { + global: + component_getFactory; + component_getImplementationEnvironment; + component_writeInfo; + local: + *; +}; diff --git a/bridges/test/java_uno/equals/types.idl b/bridges/test/java_uno/equals/types.idl new file mode 100644 index 000000000000..393e226571a4 --- /dev/null +++ b/bridges/test/java_uno/equals/types.idl @@ -0,0 +1,50 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.idl,v $ + * $Revision: 1.4 $ + * + * 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..03cf6795c596 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/Relay.java @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: Relay.java,v $ + * $Revision: 1.6 $ + * + * 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..c8f7a778f051 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/makefile.mk @@ -0,0 +1,125 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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" || "$(USE_SHELL)" != "bash" + 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" || "$(USE_SHELL)" != "bash" + 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..e32e7b22aa9d --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/readme @@ -0,0 +1,43 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: readme,v $ +# +# $Revision: 1.4 $ +# +# 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..82bc6506a51f --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolclient.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testnativethreadpoolclient.cxx,v $ + * $Revision: 1.6 $ + * + * 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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii("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::createFromAscii( + "uno:socket,host=localhost,port=3830;urp;test")), + css::uno::UNO_QUERY_THROW); + } catch (css::connection::NoConnectException & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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" void * SAL_CALL component_getFactory( + char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + char const ** envTypeName, uno_Environment **) +{ + *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} diff --git a/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx new file mode 100644 index 000000000000..bc52ec509c52 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/testnativethreadpoolserver.cxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testnativethreadpoolserver.cxx,v $ + * $Revision: 1.7 $ + * + * 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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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::createFromAscii( + "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" void * SAL_CALL component_getFactory( + char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + char const ** envTypeName, uno_Environment **) +{ + *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} diff --git a/bridges/test/java_uno/nativethreadpool/types.idl b/bridges/test/java_uno/nativethreadpool/types.idl new file mode 100644 index 000000000000..ef96a34a7357 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/types.idl @@ -0,0 +1,43 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: types.idl,v $ + * $Revision: 1.4 $ + * + * 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..717fd9778910 --- /dev/null +++ b/bridges/test/java_uno/nativethreadpool/version.map @@ -0,0 +1,39 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: version.map,v $ +# +# $Revision: 1.4 $ +# +# 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; + component_getImplementationEnvironment; + + local: + *; +}; diff --git a/bridges/test/makefile.mk b/bridges/test/makefile.mk new file mode 100644 index 000000000000..5a4cffb500ab --- /dev/null +++ b/bridges/test/makefile.mk @@ -0,0 +1,179 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.14 $ +# +# 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..cff2152dbeba --- /dev/null +++ b/bridges/test/performance/makefile.mk @@ -0,0 +1,66 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# 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) \ + $(VOSLIB) \ + $(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..1e22ac851911 --- /dev/null +++ b/bridges/test/performance/testperformance.cxx @@ -0,0 +1,193 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testperformance.cxx,v $ + * $Revision: 1.5 $ + * + * 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" ) ); + } + } + +} diff --git a/bridges/test/test_bridge.idl b/bridges/test/test_bridge.idl new file mode 100644 index 000000000000..6207a5085138 --- /dev/null +++ b/bridges/test/test_bridge.idl @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: test_bridge.idl,v $ + * $Revision: 1.4 $ + * + * 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..ce870bc19ea9 --- /dev/null +++ b/bridges/test/testclient.cxx @@ -0,0 +1,250 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testclient.cxx,v $ + * $Revision: 1.14 $ + * + * 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; +} + diff --git a/bridges/test/testclient.java b/bridges/test/testclient.java new file mode 100644 index 000000000000..e1733bbc8b10 --- /dev/null +++ b/bridges/test/testclient.java @@ -0,0 +1,159 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testclient.java,v $ + * $Revision: 1.3 $ + * + * 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..90a07ab31f43 --- /dev/null +++ b/bridges/test/testcomp.cxx @@ -0,0 +1,802 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testcomp.cxx,v $ + * $Revision: 1.12 $ + * + * 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 = OUString::createFromAscii( "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::createFromAscii( "com.sun.star.registry.ImplementationRegistration" )), + UNO_QUERY ); + + OSL_ASSERT( rReg.is() ); + OUString aDllName = sDllName; + + try + { + rReg->registerImplementation( + OUString::createFromAscii( "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; +} + + diff --git a/bridges/test/testcomp.h b/bridges/test/testcomp.h new file mode 100644 index 000000000000..d2c6e81eb20a --- /dev/null +++ b/bridges/test/testcomp.h @@ -0,0 +1,159 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testcomp.h,v $ + * $Revision: 1.9 $ + * + * 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/bridge/XServer.hpp> +//#include <com/sun/star/bridge/XClient.hpp> +#include <stdio.h> + +#include <com/sun/star/bridge/XInstanceProvider.hpp> +//#include <com/sun/star/bridge/XConnectionAdministration.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 ); diff --git a/bridges/test/testoffice.cxx b/bridges/test/testoffice.cxx new file mode 100644 index 000000000000..bf5b470d7185 --- /dev/null +++ b/bridges/test/testoffice.cxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testoffice.cxx,v $ + * $Revision: 1.10 $ + * + * 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::createFromAscii( "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::createFromAscii( "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; +} diff --git a/bridges/test/testsameprocess.cxx b/bridges/test/testsameprocess.cxx new file mode 100644 index 000000000000..1cfc44078376 --- /dev/null +++ b/bridges/test/testsameprocess.cxx @@ -0,0 +1,218 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testsameprocess.cxx,v $ + * $Revision: 1.13 $ + * + * 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; +} diff --git a/bridges/test/testserver.cxx b/bridges/test/testserver.cxx new file mode 100644 index 000000000000..61cd20f43a0a --- /dev/null +++ b/bridges/test/testserver.cxx @@ -0,0 +1,256 @@ +/************************************************************************* + * + * 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 + * + * $RCSfile: testserver.cxx,v $ + * $Revision: 1.14 $ + * + * 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::createFromAscii( "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; +} diff --git a/bridges/unotypes/makefile.mk b/bridges/unotypes/makefile.mk new file mode 100644 index 000000000000..cf6420bb6006 --- /dev/null +++ b/bridges/unotypes/makefile.mk @@ -0,0 +1,67 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.6 $ +# +# 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.bridge.XProtocolProperties \ + com.sun.star.corba.giop.MessageHeader_1_2 \ + com.sun.star.corba.giop.MsgType_1_1 \ + com.sun.star.corba.iop.ServiceContextList \ + com.sun.star.corba.iop.ProfileIdGroup \ + com.sun.star.corba.iiop.ProfileBody_1_1 \ + com.sun.star.corba.LogicalThreadID \ + com.sun.star.corba.iop.ServiceIdGroup \ + com.sun.star.corba.giop.ReplyHeader_1_2 \ + com.sun.star.corba.giop.RequestHeader_1_2 \ + com.sun.star.corba.TCKind \ + com.sun.star.corba.ObjectKey \ + com.sun.star.uno.XInterface \ + com.sun.star.lang.DisposedException \ + 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..b78a1f98510d --- /dev/null +++ b/bridges/version.mk @@ -0,0 +1,44 @@ +#************************************************************************* +# +# 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 +# +# $RCSfile: version.mk,v $ +# +# $Revision: 1.3 $ +# +# 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 + |