2010-10-14 08:30:07 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-12-05 11:46:50 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2014-06-04 16:23:19 +02:00
|
|
|
#include <rtl/instance.hxx>
|
|
|
|
#include <osl/diagnose.h>
|
2019-11-29 16:03:27 +01:00
|
|
|
#include <sal/log.hxx>
|
2014-06-04 16:23:19 +02:00
|
|
|
#include <uno/dispatcher.hxx>
|
2013-12-16 16:45:46 +01:00
|
|
|
#include <uno/lbnames.h>
|
2014-06-04 16:23:19 +02:00
|
|
|
#include <uno/mapping.hxx>
|
|
|
|
#include <cppuhelper/detail/XExceptionThrower.hpp>
|
2019-11-29 16:03:27 +01:00
|
|
|
#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
|
|
|
|
#include <com/sun/star/ucb/NameClashException.hpp>
|
2014-06-04 16:23:19 +02:00
|
|
|
#include <com/sun/star/uno/RuntimeException.hpp>
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2014-06-04 16:23:19 +02:00
|
|
|
#include <cppuhelper/exc_hlp.hxx>
|
2007-05-09 12:25:23 +00:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
using namespace ::osl;
|
|
|
|
using namespace ::cppu;
|
2007-05-09 12:25:23 +00:00
|
|
|
using namespace ::com::sun::star;
|
2003-10-06 11:55:55 +00:00
|
|
|
using namespace ::com::sun::star::uno;
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
namespace
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
|
|
|
|
2006-01-10 14:50:29 +00:00
|
|
|
using cppuhelper::detail::XExceptionThrower;
|
|
|
|
|
2014-02-25 18:02:27 +01:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
struct ExceptionThrower : public uno_Interface, XExceptionThrower
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2018-10-09 10:28:48 +02:00
|
|
|
ExceptionThrower();
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2012-03-14 13:27:56 +01:00
|
|
|
virtual ~ExceptionThrower() {}
|
|
|
|
|
2017-03-03 20:57:02 +01:00
|
|
|
static Type const & getCppuType()
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2015-04-01 08:38:16 +02:00
|
|
|
return cppu::UnoType<XExceptionThrower>::get();
|
2000-09-18 14:29:57 +00:00
|
|
|
}
|
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
// XInterface
|
2017-01-26 12:28:58 +01:00
|
|
|
virtual Any SAL_CALL queryInterface( Type const & type ) override;
|
2021-04-30 08:20:03 +02:00
|
|
|
virtual void SAL_CALL acquire() noexcept override;
|
|
|
|
virtual void SAL_CALL release() noexcept override;
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
// XExceptionThrower
|
2017-01-26 12:28:58 +01:00
|
|
|
virtual void SAL_CALL throwException( Any const & exc ) override;
|
|
|
|
virtual void SAL_CALL rethrowException() override;
|
2000-09-18 14:29:57 +00:00
|
|
|
};
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2001-03-09 11:15:28 +00:00
|
|
|
extern "C"
|
|
|
|
{
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2017-12-08 15:58:41 +02:00
|
|
|
void ExceptionThrower_acquire_release_nop(
|
2012-01-21 15:21:16 +01:00
|
|
|
SAL_UNUSED_PARAMETER uno_Interface * )
|
|
|
|
{}
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2017-12-08 15:58:41 +02:00
|
|
|
void ExceptionThrower_dispatch(
|
2003-10-06 11:55:55 +00:00
|
|
|
uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType,
|
|
|
|
void * pReturn, void * pArgs [], uno_Any ** ppException )
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2017-05-07 17:03:35 +10:00
|
|
|
OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD );
|
2000-09-18 14:29:57 +00:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription * >(
|
|
|
|
const_cast< typelib_TypeDescription * >( pMemberType ) )->
|
|
|
|
nPosition)
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2017-03-24 08:53:41 +01:00
|
|
|
case 0: // queryInterface()
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2003-10-06 11:55:55 +00:00
|
|
|
Type const & rType_demanded =
|
2015-03-31 13:13:09 +02:00
|
|
|
*static_cast< Type const * >( pArgs[ 0 ] );
|
2015-04-01 08:38:16 +02:00
|
|
|
if (rType_demanded.equals( cppu::UnoType<XInterface>::get() ) ||
|
2003-10-06 11:55:55 +00:00
|
|
|
rType_demanded.equals( ExceptionThrower::getCppuType() ))
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2015-11-10 10:13:11 +01:00
|
|
|
typelib_TypeDescription * pTD = nullptr;
|
2003-10-06 11:55:55 +00:00
|
|
|
TYPELIB_DANGER_GET( &pTD, rType_demanded.getTypeLibType() );
|
|
|
|
uno_any_construct(
|
2015-11-10 10:13:11 +01:00
|
|
|
static_cast< uno_Any * >( pReturn ), &pUnoI, pTD, nullptr );
|
2000-09-18 14:29:57 +00:00
|
|
|
TYPELIB_DANGER_RELEASE( pTD );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-10-06 11:55:55 +00:00
|
|
|
uno_any_construct(
|
2015-11-10 10:13:11 +01:00
|
|
|
static_cast< uno_Any * >( pReturn ), nullptr, nullptr, nullptr );
|
2000-09-18 14:29:57 +00:00
|
|
|
}
|
2015-11-10 10:13:11 +01:00
|
|
|
*ppException = nullptr;
|
2000-09-18 14:29:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: // acquire()
|
|
|
|
case 2: // release()
|
2015-11-10 10:13:11 +01:00
|
|
|
*ppException = nullptr;
|
2000-09-18 14:29:57 +00:00
|
|
|
break;
|
|
|
|
case 3: // throwException()
|
|
|
|
{
|
2015-03-31 13:13:09 +02:00
|
|
|
uno_Any * pAny = static_cast< uno_Any * >( pArgs[ 0 ] );
|
2017-05-07 17:03:35 +10:00
|
|
|
OSL_ASSERT( pAny->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
|
2015-11-10 10:13:11 +01:00
|
|
|
uno_type_any_construct( *ppException, pAny->pData, pAny->pType, nullptr );
|
2000-09-18 14:29:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
2017-05-07 17:03:35 +10:00
|
|
|
OSL_ASSERT( false );
|
2014-05-23 12:03:21 +02:00
|
|
|
RuntimeException exc( "not implemented!" );
|
2003-10-06 11:55:55 +00:00
|
|
|
uno_type_any_construct(
|
2015-11-10 10:13:11 +01:00
|
|
|
*ppException, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), nullptr );
|
2003-10-06 11:55:55 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-09-18 14:29:57 +00:00
|
|
|
}
|
|
|
|
}
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2001-03-09 11:15:28 +00:00
|
|
|
} // extern "C"
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
Any ExceptionThrower::queryInterface( Type const & type )
|
|
|
|
{
|
2015-04-01 08:38:16 +02:00
|
|
|
if (type.equals( cppu::UnoType<XInterface>::get() ) ||
|
2003-10-06 11:55:55 +00:00
|
|
|
type.equals( ExceptionThrower::getCppuType() ))
|
|
|
|
{
|
2019-08-27 11:06:41 +02:00
|
|
|
XExceptionThrower * that = this;
|
2003-10-06 11:55:55 +00:00
|
|
|
return Any( &that, type );
|
|
|
|
}
|
|
|
|
return Any();
|
|
|
|
}
|
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2021-04-30 08:20:03 +02:00
|
|
|
void ExceptionThrower::acquire() noexcept
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
|
|
|
}
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2021-04-30 08:20:03 +02:00
|
|
|
void ExceptionThrower::release() noexcept
|
2000-09-18 14:29:57 +00:00
|
|
|
{
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2017-01-26 12:28:58 +01:00
|
|
|
void ExceptionThrower::throwException( Any const & exc )
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
2011-03-12 12:10:42 +01:00
|
|
|
OSL_FAIL( "unexpected!" );
|
2014-12-22 11:09:57 +01:00
|
|
|
cppu::throwException( exc );
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2017-01-26 12:28:58 +01:00
|
|
|
void ExceptionThrower::rethrowException()
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2014-02-22 21:20:15 +01:00
|
|
|
|
2018-10-09 10:28:48 +02:00
|
|
|
ExceptionThrower::ExceptionThrower()
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
|
|
|
uno_Interface::acquire = ExceptionThrower_acquire_release_nop;
|
|
|
|
uno_Interface::release = ExceptionThrower_acquire_release_nop;
|
2000-09-18 14:29:57 +00:00
|
|
|
uno_Interface::pDispatcher = ExceptionThrower_dispatch;
|
|
|
|
}
|
|
|
|
|
android: Use fake exceptions on all architectures
This was previously only used for aarch64, and the
workaround does not seem to be necessary in current
Android versions on other architectures.
However, while it's e.g. not needed on an x86 AVD
with API level 21 (Android 5), at least my
x86 AVD with API level 16 (Android 4.1), which
is currently our `minSdkVersion`, fails otherwise
when trying to open any document with the below
in the ADB log.
With this (and all the previous fixes for low API/SDK levels)
in place, opening a document in Android Viewer finally
succeeds there.
> F/libc ( 3288): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 3310 (Thread-122)
> I/stderr ( 3288): terminating with uncaught exception of type com::sun::star::ucb::InteractiveAugmentedIOException
> I/stderr ( 3288): assertion "terminating with uncaught exception of type com::sun::star::ucb::InteractiveAugmentedIOException" failed: file "/usr/local/google/buildbot/src/android/ndk-release-r20/external/libcxx/../../external/libcxxabi/src/abort_message.cpp", line 73, function "abort_message"
> I/DEBUG ( 1173): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
> I/DEBUG ( 1173): Build fingerprint: 'generic_x86/sdk_x86/generic_x86:4.1.2/MASTER/eng.wdu.20191218.182616:eng/test-keys'
> I/DEBUG ( 1173): pid: 3288, tid: 3310, name: Thread-122 >>> org.libreoffice <<<
> I/DEBUG ( 1173): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
> I/DEBUG ( 1173): eax 00000000 ebx b76c9f4c ecx 00000000 edx b76cbfd4
> I/DEBUG ( 1173): esi b65ed000 edi 788c7d6c
> I/DEBUG ( 1173): xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b
> I/DEBUG ( 1173): eip b7661c03 ebp 788c7d88 esp 788c7d40 flags 00210246
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): backtrace:
> I/DEBUG ( 1173): #00 pc 00021c03 /system/lib/libc.so (abort+131)
> I/DEBUG ( 1173): #01 pc 00030ff1 /system/lib/libc.so
> I/DEBUG ( 1173): #02 pc 0e137175 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #03 pc 0e1372f5 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #04 pc 0e133d0a /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #05 pc 0e13323f /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #06 pc 0e133194 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #07 pc 0d369737 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #08 pc 0d3673b0 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #09 pc 0d366a7b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #10 pc 0d377a25 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #11 pc 09a2b944 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #12 pc 098826da /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #13 pc 098cc47c /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #14 pc 098ded29 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #15 pc 098bb839 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #16 pc 098b7e23 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #17 pc 098bb8cf /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #18 pc 0987a677 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #19 pc 0987b7c7 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #20 pc 0987ab4b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #21 pc 0987a9a7 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #22 pc 0987f90b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #23 pc 0986d4ff /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #24 pc 09872298 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #25 pc 035625cf /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #26 pc 0355dff2 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #27 pc 035713f9 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #28 pc 03570d3b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #29 pc 035714b8 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #30 pc 09a5fb66 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #31 pc 09a5f984 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): stack:
> I/DEBUG ( 1173): 788c7d00 b76cca48
> I/DEBUG ( 1173): 788c7d04 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d08 b76699eb /system/lib/libc.so (_fwalk+11)
> I/DEBUG ( 1173): 788c7d0c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d10 00000000
> I/DEBUG ( 1173): 788c7d14 00000000
> I/DEBUG ( 1173): 788c7d18 00000000
> I/DEBUG ( 1173): 788c7d1c 00000000
> I/DEBUG ( 1173): 788c7d20 00000000
> I/DEBUG ( 1173): 788c7d24 00000000
> I/DEBUG ( 1173): 788c7d28 00000000
> I/DEBUG ( 1173): 788c7d2c 00000000
> I/DEBUG ( 1173): 788c7d30 00000000
> I/DEBUG ( 1173): 788c7d34 00000000
> I/DEBUG ( 1173): 788c7d38 00000000
> I/DEBUG ( 1173): 788c7d3c 00000000
> I/DEBUG ( 1173): #00 788c7d40 00000002
> I/DEBUG ( 1173): 788c7d44 788c7d6c [stack:3310]
> I/DEBUG ( 1173): 788c7d48 00000000
> I/DEBUG ( 1173): 788c7d4c 00000115
> I/DEBUG ( 1173): 788c7d50 0000007f
> I/DEBUG ( 1173): 788c7d54 b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d58 788c7d98 [stack:3310]
> I/DEBUG ( 1173): 788c7d5c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d60 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d64 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7d68 788c7d88 [stack:3310]
> I/DEBUG ( 1173): 788c7d6c fffffbdf
> I/DEBUG ( 1173): 788c7d70 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d74 b76b3b24 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d78 b7661b8e /system/lib/libc.so (abort+14)
> I/DEBUG ( 1173): 788c7d7c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): ........ ........
> I/DEBUG ( 1173): #01 788c7d90 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d94 b76b3b24 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d98 b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7d9c 8723cac3 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7da0 00000049
> I/DEBUG ( 1173): 788c7da4 8723cb39 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7da8 b766b6fe /system/lib/libc.so (vasprintf+14)
> I/DEBUG ( 1173): 788c7dac 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7db0 b7670fa9 /system/lib/libc.so (__assert2+9)
> I/DEBUG ( 1173): 788c7db4 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7db8 788c7df8 [stack:3310]
> I/DEBUG ( 1173): 788c7dbc 86a0d175 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #02 788c7dc0 8723cac3 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7dc4 00000049
> I/DEBUG ( 1173): 788c7dc8 8723cb39 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7dcc b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7dd0 b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7dd4 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7dd8 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7ddc 86a09960 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7de0 00000014
> I/DEBUG ( 1173): 788c7de4 86a09980 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7de8 788c7e38 [stack:3310]
> I/DEBUG ( 1173): 788c7dec 788c7e1c [stack:3310]
> I/DEBUG ( 1173): 788c7df0 b9b1c480 [heap]
> I/DEBUG ( 1173): 788c7df4 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7df8 788c8238 [stack:3310]
> I/DEBUG ( 1173): 788c7dfc 86a0d2f5 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): memory map around fault addr deadbaad:
> I/DEBUG ( 1173): bfa03000-bfa24000 [stack]
> I/DEBUG ( 1173): (no map for address)
> I/DEBUG ( 1173): (no map above)
> D/Zygote ( 1176): Process 3288 terminated by signal (11)
Change-Id: I0bc6d13b1217959c5e447e7c6126006b561639a4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133264
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2022-04-21 14:26:18 +02:00
|
|
|
#if defined(IOS) || defined(ANDROID) || defined(EMSCRIPTEN)
|
2021-09-25 18:03:31 +02:00
|
|
|
#define RETHROW_FAKE_EXCEPTIONS 1
|
|
|
|
#else
|
|
|
|
#define RETHROW_FAKE_EXCEPTIONS 0
|
|
|
|
#endif
|
|
|
|
|
2011-04-04 13:09:33 +01:00
|
|
|
class theExceptionThrower : public rtl::Static<ExceptionThrower, theExceptionThrower> {};
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2021-09-25 18:03:31 +02:00
|
|
|
#if RETHROW_FAKE_EXCEPTIONS
|
2019-11-29 16:03:27 +01:00
|
|
|
// In the native iOS / Android app, where we don't have any Java, Python,
|
|
|
|
// BASIC, or other scripting, the only thing that would use the C++/UNO bridge
|
|
|
|
// functionality that invokes codeSnippet() was cppu::throwException().
|
|
|
|
//
|
|
|
|
// codeSnippet() is part of what corresponds to the code that uses
|
|
|
|
// run-time-generated machine code on other platforms. We can't generate code
|
|
|
|
// at run-time on iOS, that has been known forever.
|
|
|
|
//
|
|
|
|
// Instead of digging in and trying to understand what is wrong, another
|
|
|
|
// solution was chosen. It turns out that the number of types of exception
|
|
|
|
// objects thrown by cppu::throwException() is fairly small. During startup of
|
|
|
|
// the LibreOffice code, and loading of an .odt document, only one kind of
|
|
|
|
// exception is thrown this way... (The lovely
|
|
|
|
// css::ucb:InteractiveAugmentedIOException.)
|
|
|
|
//
|
|
|
|
// So we can simply have code that checks what the type of object being thrown
|
2019-12-05 14:39:30 +01:00
|
|
|
// is, and explicitly throws such an object then with a normal C++ throw
|
2019-11-29 16:03:27 +01:00
|
|
|
// statement. Seems to work.
|
|
|
|
template <class E> void tryThrow(css::uno::Any const& aException)
|
|
|
|
{
|
|
|
|
E aSpecificException;
|
|
|
|
if (aException >>= aSpecificException)
|
|
|
|
throw aSpecificException;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lo_mobile_throwException(css::uno::Any const& aException)
|
|
|
|
{
|
|
|
|
assert(aException.getValueTypeClass() == css::uno::TypeClass_EXCEPTION);
|
|
|
|
|
|
|
|
tryThrow<css::ucb::InteractiveAugmentedIOException>(aException);
|
|
|
|
tryThrow<css::ucb::NameClashException>(aException);
|
|
|
|
tryThrow<css::uno::RuntimeException>(aException);
|
|
|
|
|
|
|
|
SAL_WARN("cppuhelper", "lo_mobile_throwException: Unhandled exception type: " << aException.getValueTypeName());
|
|
|
|
|
|
|
|
assert(false);
|
|
|
|
}
|
2021-09-25 18:03:31 +02:00
|
|
|
#endif // RETHROW_FAKE_EXCEPTIONS
|
2019-11-29 16:03:27 +01:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
|
|
namespace cppu
|
|
|
|
{
|
|
|
|
|
2014-02-25 18:02:27 +01:00
|
|
|
|
2014-06-05 08:08:06 +02:00
|
|
|
void SAL_CALL throwException( Any const & exc )
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
|
|
|
if (exc.getValueTypeClass() != TypeClass_EXCEPTION)
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2013-01-30 11:44:23 +01:00
|
|
|
"no UNO exception given "
|
2014-05-23 12:03:21 +02:00
|
|
|
"(must be derived from com::sun::star::uno::Exception)!" );
|
2000-09-18 14:29:57 +00:00
|
|
|
}
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2021-09-25 18:03:31 +02:00
|
|
|
#if RETHROW_FAKE_EXCEPTIONS
|
2019-11-29 16:03:27 +01:00
|
|
|
lo_mobile_throwException(exc);
|
Re-think cppu::throwException() and the C++/UNO bridge on iOS
It seems that on iOS, where we don't have any Java, Python, BASIC, or
other scripting, the only thing that would use the C++/UNO bridge
functionality that invokes codeSnippet() was cppu::throwException().
codeSnippet() is part of what corresponds to the code that uses
run-time-generated machine code on other platforms. We can't generate
code at run-time on iOS, that has been known forever. Instead we have
used some manually written assembler to handle it instead. We used to
have a Perl script to generate a set of code snippets for different
cases, different numbers of parameters of the called function and
whatnot, but that went away at some stage some year ago. (It is
unclear whether that broke the C++/UNO bridge on iOS, or whether the
stuff continued to work even after that.)
Anyway, this handwritten assembly, or the manual construction of
internal data structures for exceptions, or something else, seemed to
have bit-rotten. Exceptions thrown with cppu::throwException() were
not catchable properly any longer.
Instead of digging in and trying to understand what is wrong, I chose
another solution. It turns out that the number of types of exception
objects thrown by cppu::throwException() is fairly small. During
startup of the LibreOffice code, and loading of an .odt document, only
one kind of exception is thrown this way... (The lovely
css::ucb:InteractiveAugmentedIOException.)
So we can simply have code that checks what the type of object being
thrown is, and explicitgly throws such an object then with a normal
C++ throw statement. Seems to work.
Sadly the cppu::getCaughtException() API still needs some inline
assembly in the C++/UNO brige. That seems to work though, knock on
wood.
This commit also adds a small "unit test" for iOS, copied from
cppuhelperm to ImplSVMain(). Ideally we should not copy code around of
course, but have a separate unit test app for iOS that would somehow
include relevant unit tests from source files all over the place.
Later.
Change-Id: Ib6d9d5b6fb8cc684ec15c97a312ca2f720e87069
Reviewed-on: https://gerrit.libreoffice.org/60506
Tested-by: Jenkins
Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-09-12 22:06:18 +03:00
|
|
|
#else
|
2013-01-30 11:44:23 +01:00
|
|
|
Mapping uno2cpp(Environment(UNO_LB_UNO), Environment::getCurrent());
|
2003-10-06 11:55:55 +00:00
|
|
|
if (! uno2cpp.is())
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"cannot get binary UNO to C++ mapping!" );
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Reference< XExceptionThrower > xThrower;
|
|
|
|
uno2cpp.mapInterface(
|
|
|
|
reinterpret_cast< void ** >( &xThrower ),
|
2011-04-04 13:09:33 +01:00
|
|
|
static_cast< uno_Interface * >( &theExceptionThrower::get() ),
|
2003-10-06 11:55:55 +00:00
|
|
|
ExceptionThrower::getCppuType() );
|
2017-05-07 17:03:35 +10:00
|
|
|
OSL_ASSERT( xThrower.is() );
|
2003-10-06 11:55:55 +00:00
|
|
|
xThrower->throwException( exc );
|
2021-09-25 18:03:31 +02:00
|
|
|
#endif // !RETHROW_FAKE_EXCEPTIONS
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
2014-02-25 18:02:27 +01:00
|
|
|
|
2003-10-06 11:55:55 +00:00
|
|
|
Any SAL_CALL getCaughtException()
|
|
|
|
{
|
2021-09-25 18:03:31 +02:00
|
|
|
// why does this differ from RETHROW_FAKE_EXCEPTIONS?
|
android: Use fake exceptions on all architectures
This was previously only used for aarch64, and the
workaround does not seem to be necessary in current
Android versions on other architectures.
However, while it's e.g. not needed on an x86 AVD
with API level 21 (Android 5), at least my
x86 AVD with API level 16 (Android 4.1), which
is currently our `minSdkVersion`, fails otherwise
when trying to open any document with the below
in the ADB log.
With this (and all the previous fixes for low API/SDK levels)
in place, opening a document in Android Viewer finally
succeeds there.
> F/libc ( 3288): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 3310 (Thread-122)
> I/stderr ( 3288): terminating with uncaught exception of type com::sun::star::ucb::InteractiveAugmentedIOException
> I/stderr ( 3288): assertion "terminating with uncaught exception of type com::sun::star::ucb::InteractiveAugmentedIOException" failed: file "/usr/local/google/buildbot/src/android/ndk-release-r20/external/libcxx/../../external/libcxxabi/src/abort_message.cpp", line 73, function "abort_message"
> I/DEBUG ( 1173): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
> I/DEBUG ( 1173): Build fingerprint: 'generic_x86/sdk_x86/generic_x86:4.1.2/MASTER/eng.wdu.20191218.182616:eng/test-keys'
> I/DEBUG ( 1173): pid: 3288, tid: 3310, name: Thread-122 >>> org.libreoffice <<<
> I/DEBUG ( 1173): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
> I/DEBUG ( 1173): eax 00000000 ebx b76c9f4c ecx 00000000 edx b76cbfd4
> I/DEBUG ( 1173): esi b65ed000 edi 788c7d6c
> I/DEBUG ( 1173): xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b
> I/DEBUG ( 1173): eip b7661c03 ebp 788c7d88 esp 788c7d40 flags 00210246
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): backtrace:
> I/DEBUG ( 1173): #00 pc 00021c03 /system/lib/libc.so (abort+131)
> I/DEBUG ( 1173): #01 pc 00030ff1 /system/lib/libc.so
> I/DEBUG ( 1173): #02 pc 0e137175 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #03 pc 0e1372f5 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #04 pc 0e133d0a /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #05 pc 0e13323f /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #06 pc 0e133194 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #07 pc 0d369737 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #08 pc 0d3673b0 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #09 pc 0d366a7b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #10 pc 0d377a25 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #11 pc 09a2b944 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #12 pc 098826da /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #13 pc 098cc47c /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #14 pc 098ded29 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #15 pc 098bb839 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #16 pc 098b7e23 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #17 pc 098bb8cf /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #18 pc 0987a677 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #19 pc 0987b7c7 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #20 pc 0987ab4b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #21 pc 0987a9a7 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #22 pc 0987f90b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #23 pc 0986d4ff /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #24 pc 09872298 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #25 pc 035625cf /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #26 pc 0355dff2 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #27 pc 035713f9 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #28 pc 03570d3b /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #29 pc 035714b8 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #30 pc 09a5fb66 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #31 pc 09a5f984 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): stack:
> I/DEBUG ( 1173): 788c7d00 b76cca48
> I/DEBUG ( 1173): 788c7d04 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d08 b76699eb /system/lib/libc.so (_fwalk+11)
> I/DEBUG ( 1173): 788c7d0c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d10 00000000
> I/DEBUG ( 1173): 788c7d14 00000000
> I/DEBUG ( 1173): 788c7d18 00000000
> I/DEBUG ( 1173): 788c7d1c 00000000
> I/DEBUG ( 1173): 788c7d20 00000000
> I/DEBUG ( 1173): 788c7d24 00000000
> I/DEBUG ( 1173): 788c7d28 00000000
> I/DEBUG ( 1173): 788c7d2c 00000000
> I/DEBUG ( 1173): 788c7d30 00000000
> I/DEBUG ( 1173): 788c7d34 00000000
> I/DEBUG ( 1173): 788c7d38 00000000
> I/DEBUG ( 1173): 788c7d3c 00000000
> I/DEBUG ( 1173): #00 788c7d40 00000002
> I/DEBUG ( 1173): 788c7d44 788c7d6c [stack:3310]
> I/DEBUG ( 1173): 788c7d48 00000000
> I/DEBUG ( 1173): 788c7d4c 00000115
> I/DEBUG ( 1173): 788c7d50 0000007f
> I/DEBUG ( 1173): 788c7d54 b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d58 788c7d98 [stack:3310]
> I/DEBUG ( 1173): 788c7d5c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d60 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d64 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7d68 788c7d88 [stack:3310]
> I/DEBUG ( 1173): 788c7d6c fffffbdf
> I/DEBUG ( 1173): 788c7d70 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d74 b76b3b24 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d78 b7661b8e /system/lib/libc.so (abort+14)
> I/DEBUG ( 1173): 788c7d7c b76c9f4c /system/lib/libc.so
> I/DEBUG ( 1173): ........ ........
> I/DEBUG ( 1173): #01 788c7d90 b76ca208 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d94 b76b3b24 /system/lib/libc.so
> I/DEBUG ( 1173): 788c7d98 b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7d9c 8723cac3 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7da0 00000049
> I/DEBUG ( 1173): 788c7da4 8723cb39 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7da8 b766b6fe /system/lib/libc.so (vasprintf+14)
> I/DEBUG ( 1173): 788c7dac 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7db0 b7670fa9 /system/lib/libc.so (__assert2+9)
> I/DEBUG ( 1173): 788c7db4 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7db8 788c7df8 [stack:3310]
> I/DEBUG ( 1173): 788c7dbc 86a0d175 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): #02 788c7dc0 8723cac3 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7dc4 00000049
> I/DEBUG ( 1173): 788c7dc8 8723cb39 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7dcc b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7dd0 b9b98fc0 [heap]
> I/DEBUG ( 1173): 788c7dd4 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7dd8 788c7e04 [stack:3310]
> I/DEBUG ( 1173): 788c7ddc 86a09960 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7de0 00000014
> I/DEBUG ( 1173): 788c7de4 86a09980 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7de8 788c7e38 [stack:3310]
> I/DEBUG ( 1173): 788c7dec 788c7e1c [stack:3310]
> I/DEBUG ( 1173): 788c7df0 b9b1c480 [heap]
> I/DEBUG ( 1173): 788c7df4 8d73b830 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173): 788c7df8 788c8238 [stack:3310]
> I/DEBUG ( 1173): 788c7dfc 86a0d2f5 /data/data/org.libreoffice/lib/liblo-native-code.so
> I/DEBUG ( 1173):
> I/DEBUG ( 1173): memory map around fault addr deadbaad:
> I/DEBUG ( 1173): bfa03000-bfa24000 [stack]
> I/DEBUG ( 1173): (no map for address)
> I/DEBUG ( 1173): (no map above)
> D/Zygote ( 1176): Process 3288 terminated by signal (11)
Change-Id: I0bc6d13b1217959c5e447e7c6126006b561639a4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133264
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2022-04-21 14:26:18 +02:00
|
|
|
#if defined(ANDROID) || defined(EMSCRIPTEN)
|
2019-11-29 16:03:27 +01:00
|
|
|
return Any();
|
|
|
|
#else
|
2013-01-30 11:44:23 +01:00
|
|
|
Mapping cpp2uno(Environment::getCurrent(), Environment(UNO_LB_UNO));
|
2003-10-06 11:55:55 +00:00
|
|
|
if (! cpp2uno.is())
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"cannot get C++ to binary UNO mapping!" );
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
2013-01-30 11:44:23 +01:00
|
|
|
Mapping uno2cpp(Environment(UNO_LB_UNO), Environment::getCurrent());
|
2003-10-06 11:55:55 +00:00
|
|
|
if (! uno2cpp.is())
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"cannot get binary UNO to C++ mapping!" );
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 10:13:11 +01:00
|
|
|
typelib_TypeDescription * pTD = nullptr;
|
2003-10-06 11:55:55 +00:00
|
|
|
TYPELIB_DANGER_GET(
|
|
|
|
&pTD, ExceptionThrower::getCppuType().getTypeLibType() );
|
|
|
|
|
|
|
|
UnoInterfaceReference unoI;
|
|
|
|
cpp2uno.mapInterface(
|
|
|
|
reinterpret_cast< void ** >( &unoI.m_pUnoI ),
|
2011-04-04 13:09:33 +01:00
|
|
|
static_cast< XExceptionThrower * >( &theExceptionThrower::get() ), pTD );
|
2017-05-07 17:03:35 +10:00
|
|
|
OSL_ASSERT( unoI.is() );
|
2003-10-06 11:55:55 +00:00
|
|
|
|
2015-11-10 10:13:11 +01:00
|
|
|
typelib_TypeDescription * pMemberTD = nullptr;
|
2003-10-06 11:55:55 +00:00
|
|
|
TYPELIB_DANGER_GET(
|
|
|
|
&pMemberTD,
|
|
|
|
reinterpret_cast< typelib_InterfaceTypeDescription * >( pTD )->
|
|
|
|
ppMembers[ 1 ] /* rethrowException() */ );
|
|
|
|
|
|
|
|
uno_Any exc_mem;
|
|
|
|
uno_Any * exc = &exc_mem;
|
2015-11-10 10:13:11 +01:00
|
|
|
unoI.dispatch( pMemberTD, nullptr, nullptr, &exc );
|
2003-10-06 11:55:55 +00:00
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pMemberTD );
|
|
|
|
TYPELIB_DANGER_RELEASE( pTD );
|
|
|
|
|
2015-11-10 10:13:11 +01:00
|
|
|
if (exc == nullptr)
|
2003-10-06 11:55:55 +00:00
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "rethrowing C++ exception failed!" );
|
2003-10-06 11:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Any ret;
|
2006-06-19 09:33:12 +00:00
|
|
|
uno_any_destruct( &ret, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
|
2003-10-06 11:55:55 +00:00
|
|
|
uno_type_any_constructAndConvert(
|
|
|
|
&ret, exc->pData, exc->pType, uno2cpp.get() );
|
2015-11-10 10:13:11 +01:00
|
|
|
uno_any_destruct( exc, nullptr );
|
2003-10-06 11:55:55 +00:00
|
|
|
return ret;
|
2019-11-29 16:03:27 +01:00
|
|
|
#endif
|
2000-09-18 14:29:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-10-14 08:30:07 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|