Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / cc50_solaris_intel / except.cxx
blobe2ce7a1f0e23bcd8e6df06e2e8ab460404ff3c9c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <cstddef>
31 #include <dlfcn.h>
32 #include <new.h>
33 #include <typeinfo>
34 #include <list>
35 #include <map>
36 #include <rtl/alloc.h>
37 #include <rtl/instance.hxx>
38 #include <osl/diagnose.h>
40 #include <rtl/strbuf.hxx>
41 #include <typelib/typedescription.hxx>
42 #include <com/sun/star/uno/Any.hxx>
44 #include "bridges/cpp_uno/shared/arraypointer.hxx"
46 #include "cc50_solaris_intel.hxx"
48 #include <hash.cxx>
50 // need a += operator for OString and sal_Char
51 using ::rtl::OUString;
52 using ::rtl::OString;
53 using ::rtl::OStringBuffer;
54 using ::rtl::OUStringToOString;
55 using ::rtl::OStringToOUString;
57 inline OString& operator+=( OString& rString, sal_Char cAdd )
59 sal_Char add[2];
60 add[0] = cAdd;
61 add[1] = 0;
62 return rString += add;
66 using namespace std;
67 using namespace osl;
68 using namespace com::sun::star::uno;
70 namespace CPPU_CURRENT_NAMESPACE
73 static OString toUNOname( const OString & rRTTIname )
75 OString aRet;
77 const sal_Char* pRTTI = rRTTIname.getStr();
78 const sal_Char* pOrg = pRTTI;
79 const sal_Char* pLast = pRTTI;
81 while( 1 )
83 if( *pRTTI == ':' || ! *pRTTI )
85 if( aRet.getLength() )
86 aRet += ".";
87 aRet += rRTTIname.copy( pLast - pOrg, pRTTI - pLast );
88 while( *pRTTI == ':' )
89 pRTTI++;
90 pLast = pRTTI;
91 if( ! *pRTTI )
92 break;
94 else
95 pRTTI++;
98 return aRet;
100 //==================================================================================================
101 static OString toRTTIname( const OString & rUNOname )
103 OStringBuffer aRet( rUNOname.getLength()*2 );
105 sal_Int32 nIndex = 0;
108 if( nIndex > 0 )
109 aRet.append( "::" );
110 aRet.append( rUNOname.getToken( 0, '.', nIndex ) );
111 } while( nIndex != -1 );
113 return aRet.makeStringAndClear();
115 //==================================================================================================
117 static OString toRTTImangledname( const OString & rRTTIname )
119 if( ! rRTTIname.getLength() )
120 return OString();
122 OStringBuffer aRet( rRTTIname.getLength()*2 );
124 aRet.append( "__1n" );
125 sal_Int32 nIndex = 0;
128 OString aToken( rRTTIname.getToken( 0, ':', nIndex ) );
129 int nBytes = aToken.getLength();
130 if( nBytes )
132 if( nBytes > 25 )
134 aRet.append( (sal_Char)( nBytes/26 + 'a' ) );
135 aRet.append( (sal_Char)( nBytes%26 + 'A' ) );
137 else
138 aRet.append( (sal_Char)( nBytes + 'A' ) );
139 for (sal_Int32 i = 0; i < aToken.getLength(); ++i) {
140 char c = aToken[i];
141 if (c == 'Q') {
142 aRet.append("QdD");
143 } else {
144 aRet.append(c);
148 } while( nIndex != -1 );
150 aRet.append( '_' );
152 return aRet.makeStringAndClear();
155 //##################################################################################################
156 //#### RTTI simulation #############################################################################
157 //##################################################################################################
159 class RTTIHolder
161 std::map< OString, void* > aAllRTTI;
162 public:
163 ~RTTIHolder();
165 void* getRTTI( const OString& rTypename );
166 void* getRTTI_UnoName( const OString& rUnoTypename )
167 { return getRTTI( toRTTIname( rUnoTypename ) ); }
169 void* insertRTTI( const OString& rTypename );
170 void* insertRTTI_UnoName( const OString& rTypename )
171 { return insertRTTI( toRTTIname( rTypename ) ); }
172 void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr );
175 RTTIHolder::~RTTIHolder()
177 for ( std::map< OString, void* >::const_iterator iPos( aAllRTTI.begin() );
178 iPos != aAllRTTI.end(); ++iPos )
180 delete[] static_cast< char * >(iPos->second);
184 #if OSL_DEBUG_LEVEL > 1
185 #include <stdio.h>
186 #endif
188 void* RTTIHolder::getRTTI( const OString& rTypename )
190 std::map< OString, void* >::iterator element;
192 element = aAllRTTI.find( rTypename );
193 if( element != aAllRTTI.end() )
194 return (*element).second;
196 // create rtti structure
197 element = aAllRTTI.find( rTypename );
198 if( element != aAllRTTI.end() )
199 return (*element).second;
201 return NULL;
204 static long nMagicId = 1;
206 void* RTTIHolder::insertRTTI( const OString& rTypename )
208 OString aMangledName( toRTTImangledname( rTypename ) );
209 NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() );
212 // rSuperTypename MUST exist !!!
213 std::size_t const RTTI_SIZE = 19; // 14???
214 void** pRTTI = reinterpret_cast< void ** >(
215 new char[RTTI_SIZE * sizeof (void *) + strlen(rTypename.getStr()) + 1]);
216 pRTTI[ 0 ] = reinterpret_cast< void * >(RTTI_SIZE * sizeof (void *));
217 pRTTI[ 1 ] = NULL;
218 pRTTI[ 2 ] = (void*)(7*sizeof(void*));
219 pRTTI[ 3 ] = (void*)aHash.getHash()[0];
220 pRTTI[ 4 ] = (void*)aHash.getHash()[1];
221 pRTTI[ 5 ] = (void*)aHash.getHash()[2];
222 pRTTI[ 6 ] = (void*)aHash.getHash()[3];
223 pRTTI[ 7 ] = NULL;
224 pRTTI[ 8 ] = NULL;
226 pRTTI[ 9 ] = pRTTI[ 3 ];
227 pRTTI[ 10 ] = pRTTI[ 4 ];
228 pRTTI[ 11 ] = pRTTI[ 5 ];
229 pRTTI[ 12 ] = pRTTI[ 6 ];
230 pRTTI[ 13 ] = (void*)0x80000000;
231 strcpy(reinterpret_cast< char * >(pRTTI + RTTI_SIZE), rTypename.getStr());
233 aAllRTTI[ rTypename ] = (void*)pRTTI;
234 #if OSL_DEBUG_LEVEL > 1
235 fprintf( stderr,
236 "generating base RTTI for type %s:\n"
237 " mangled: %s\n"
238 " hash: %.8x %.8x %.8x %.8x\n",
239 rTypename.getStr(),
240 aMangledName.getStr(),
241 pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ]
243 #endif
244 return pRTTI;
247 void* RTTIHolder::generateRTTI( typelib_CompoundTypeDescription * pCompTypeDescr )
249 OString aUNOCompTypeName( OUStringToOString( pCompTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US ) );
250 OString aRTTICompTypeName( toRTTIname( aUNOCompTypeName ) );
252 void* pHaveRTTI = getRTTI( aRTTICompTypeName );
253 if( pHaveRTTI )
254 return pHaveRTTI;
256 if( ! pCompTypeDescr->pBaseTypeDescription )
257 // this is a base type
258 return insertRTTI( aRTTICompTypeName );
260 // get base class RTTI
261 void* pSuperRTTI = generateRTTI( pCompTypeDescr->pBaseTypeDescription );
262 OSL_ENSURE( pSuperRTTI, "could not generate RTTI for supertype !" );
264 // find out the size to allocate for RTTI
265 void** pInherit = (void**)((sal_uInt32)pSuperRTTI + ((sal_uInt32*)pSuperRTTI)[2] + 8);
266 int nInherit;
267 for( nInherit = 1; pInherit[ nInherit*5-1 ] != (void*)0x80000000; nInherit++ )
270 OString aMangledName( toRTTImangledname( aRTTICompTypeName ) );
271 NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() );
273 std::size_t const rttiSize = 14 + nInherit * 5;
274 void** pRTTI = reinterpret_cast< void ** >(
275 new char[
276 rttiSize * sizeof (void *)
277 + strlen(aRTTICompTypeName.getStr()) + 1]);
278 pRTTI[ 0 ] = reinterpret_cast< void * >(rttiSize * sizeof (void *));
279 pRTTI[ 1 ] = NULL;
280 pRTTI[ 2 ] = (void*)(7*sizeof(void*));
281 pRTTI[ 3 ] = (void*)aHash.getHash()[0];
282 pRTTI[ 4 ] = (void*)aHash.getHash()[1];
283 pRTTI[ 5 ] = (void*)aHash.getHash()[2];
284 pRTTI[ 6 ] = (void*)aHash.getHash()[3];
285 pRTTI[ 7 ] = NULL;
286 pRTTI[ 8 ] = NULL;
288 memcpy( pRTTI+9, pInherit, 4*nInherit*5 );
289 pRTTI[ 8 +nInherit*5 ] = NULL;
290 pRTTI[ 9 +nInherit*5 ] = pRTTI[ 3 ];
291 pRTTI[ 10+nInherit*5 ] = pRTTI[ 4 ];
292 pRTTI[ 11+nInherit*5 ] = pRTTI[ 5 ];
293 pRTTI[ 12+nInherit*5 ] = pRTTI[ 6 ];
294 pRTTI[ 13+nInherit*5 ] = (void*)0x80000000;
295 strcpy(
296 reinterpret_cast< char * >(pRTTI + rttiSize),
297 aRTTICompTypeName.getStr());
299 aAllRTTI[ aRTTICompTypeName ] = (void*)pRTTI;
301 #if OSL_DEBUG_LEVEL > 1
302 fprintf( stderr,
303 "generating struct RTTI for type %s:\n"
304 " mangled: %s\n"
305 " hash: %.8x %.8x %.8X %.8x\n",
306 aRTTICompTypeName.getStr(),
307 aMangledName.getStr(),
308 pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ]
310 #endif
312 return pRTTI;
315 struct RTTISingleton: public rtl::Static< RTTIHolder, RTTISingleton > {};
317 //__________________________________________________________________________________________________
319 static void deleteException(
320 void* pExc, unsigned char* thunk, typelib_TypeDescription* pType )
322 uno_destructData(
323 pExc, pType, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
324 typelib_typedescription_release( pType );
325 delete[] thunk;
328 //__________________________________________________________________________________________________
330 //##################################################################################################
331 //#### exported ####################################################################################
332 //##################################################################################################
334 void cc50_solaris_intel_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
336 #if OSL_DEBUG_LEVEL > 1
337 OString cstr(
338 OUStringToOString(
339 *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
340 RTL_TEXTENCODING_ASCII_US ) );
341 fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
342 #endif
343 bridges::cpp_uno::shared::ArrayPointer< unsigned char > thunkPtr(
344 new unsigned char[24]);
345 typelib_TypeDescription * pTypeDescr = 0;
346 // will be released by deleteException
347 typelib_typedescriptionreference_getDescription( &pTypeDescr, pUnoExc->pType );
349 void * pRTTI = RTTISingleton::get().generateRTTI( (typelib_CompoundTypeDescription *)pTypeDescr );
351 // a must be
352 OSL_ENSURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" );
354 void * pCppExc = __Crun::ex_alloc( pTypeDescr->nSize );
355 uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
357 // destruct uno exception
358 uno_any_destruct( pUnoExc, 0 );
360 unsigned char * thunk = thunkPtr.release();
361 // movl %esp, %ecx:
362 thunk[0] = 0x8B;
363 thunk[1] = 0xCC;
364 // pushl pTypeDescr:
365 thunk[2] = 0x68;
366 *reinterpret_cast< void ** >(thunk + 3) = pTypeDescr;
367 // pushl thunk:
368 thunk[7] = 0x68;
369 *reinterpret_cast< void ** >(thunk + 8) = thunk;
370 // pushl 4(%ecx):
371 thunk[12] = 0xFF;
372 thunk[13] = 0x71;
373 thunk[14] = 0x04;
374 // call deleteException:
375 thunk[15] = 0xE8;
376 #pragma disable_warn
377 void * d = reinterpret_cast< void * >(deleteException);
378 #pragma enable_warn
379 *reinterpret_cast< std::ptrdiff_t * >(thunk + 16) =
380 static_cast< unsigned char * >(d) - (thunk + 20);
381 // addl $12, %esp:
382 thunk[20] = 0x83;
383 thunk[21] = 0xC4;
384 thunk[22] = 0x0C;
385 // ret:
386 thunk[23] = 0xC3;
388 #pragma disable_warn
389 void (* f)(void *) = reinterpret_cast< void (*)(void *) >(thunk);
390 #pragma enable_warn
391 __Crun::ex_throw(pCppExc, (const __Crun::static_type_info*)pRTTI, f);
394 void cc50_solaris_intel_fillUnoException(
395 void* pCppExc,
396 const char* pInfo,
397 uno_Any* pUnoExc,
398 uno_Mapping * pCpp2Uno )
400 OSL_ASSERT( pInfo != 0 );
401 OString uno_name( toUNOname( pInfo ) );
402 OUString aName( OStringToOUString(
403 uno_name, RTL_TEXTENCODING_ASCII_US ) );
404 typelib_TypeDescription * pExcTypeDescr = 0;
405 typelib_typedescription_getByName( &pExcTypeDescr, aName.pData );
407 if (pExcTypeDescr == 0) // the thing that should not be
409 RuntimeException aRE(
410 OUString( RTL_CONSTASCII_USTRINGPARAM(
411 "exception type not found: ") ) + aName,
412 Reference< XInterface >() );
413 Type const & rType = ::getCppuType( &aRE );
414 uno_type_any_constructAndConvert(
415 pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
416 #if OSL_DEBUG_LEVEL > 0
417 OString cstr( OUStringToOString(
418 aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
419 OSL_FAIL( cstr.getStr() );
420 #endif
421 return;
424 #if OSL_DEBUG_LEVEL > 1
425 fprintf( stderr, "> c++ exception occurred: %s\n",
426 ::rtl::OUStringToOString(
427 pExcTypeDescr->pTypeName,
428 RTL_TEXTENCODING_ASCII_US ).getStr() );
429 #endif
430 // construct uno exception any
431 uno_any_constructAndConvert(
432 pUnoExc, pCppExc, pExcTypeDescr, pCpp2Uno );
433 typelib_typedescription_release( pExcTypeDescr );
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */