diff options
Diffstat (limited to 'sal/osl/all')
-rw-r--r-- | sal/osl/all/compat.cxx | 197 | ||||
-rw-r--r-- | sal/osl/all/debugbase.cxx | 145 | ||||
-rw-r--r-- | sal/osl/all/filepath.cxx | 113 | ||||
-rw-r--r-- | sal/osl/all/loadmodulerelative.cxx | 60 | ||||
-rw-r--r-- | sal/osl/all/log.cxx | 477 | ||||
-rw-r--r-- | sal/osl/all/mutexshared.cxx | 20 | ||||
-rw-r--r-- | sal/osl/all/signalshared.cxx | 141 | ||||
-rw-r--r-- | sal/osl/all/utility.cxx | 49 |
8 files changed, 1202 insertions, 0 deletions
diff --git a/sal/osl/all/compat.cxx b/sal/osl/all/compat.cxx new file mode 100644 index 000000000..8fafc628b --- /dev/null +++ b/sal/osl/all/compat.cxx @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <cstdlib> + +#include <osl/module.h> +#include <osl/pipe.h> +#include <osl/socket.h> +#include <osl/time.h> +#include <sal/types.h> + +// Stubs for removed functionality, to be killed when we bump sal SONAME + +extern "C" { + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_acquireSemaphore(void *) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC void SAL_CALL osl_addToSocketSet(void *, oslSocket) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT int SAL_CALL osl_areCommandArgsSet() { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_assertFailedLine( + char const *, sal_Int32, char const *) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL osl_breakDebug() { + std::abort(); +} + +SAL_DLLPUBLIC void SAL_CALL osl_clearSocketSet(void *) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL osl_createSemaphore(sal_uInt32) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC void * SAL_CALL osl_createSocketSet() { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC sal_Int32 SAL_CALL osl_demultiplexSocketEvents( + void *, void *, void *, TimeValue const *) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL osl_destroySemaphore(void *) { + std::abort(); +} + +SAL_DLLPUBLIC void SAL_CALL osl_destroySocketSet(void *) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_getEthernetAddress(sal_uInt8 *) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC sal_Bool SAL_CALL osl_isInSocketSet(void *, oslSocket) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_releaseSemaphore(void *) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT sal_Int32 SAL_CALL osl_reportError( + sal_uInt32, char const *) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC void SAL_CALL osl_removeFromSocketSet(void *, oslSocket) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe, oslSocket) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +namespace { +typedef void (* pfunc_osl_printDebugMessage)(char const *); +} +SAL_DLLPUBLIC_EXPORT pfunc_osl_printDebugMessage SAL_CALL +osl_setDebugMessageFunc(pfunc_osl_printDebugMessage) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +namespace { +typedef void (* pfunc_osl_printDetailedDebugMessage)( + char const *, sal_Int32, char const *); +} +SAL_DLLPUBLIC_EXPORT pfunc_osl_printDetailedDebugMessage SAL_CALL +osl_setDetailedDebugMessageFunc(pfunc_osl_printDetailedDebugMessage) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL osl_trace(char const *, ...) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL osl_tryToAcquireSemaphore(void *) { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT sal_Int32 SAL_CALL rtl_addUnloadingListener( + void (SAL_CALL *)(void *), void *) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT sal_Int32 SAL_CALL rtl_compareMemory( + void const *, void const *, sal_Size) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_copyMemory( + void *, void const *, sal_Size) +{ + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_fillMemory(void *, sal_Size, sal_uInt8) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL rtl_findInMemory( + void const *, sal_uInt8, sal_Size) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_moveMemory( + void *, void const *, sal_Size) +{ + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL rtl_registerModuleForUnloading(oslModule) +{ + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_removeUnloadingListener(sal_Int32) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_unloadUnusedModules(TimeValue *) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_unregisterModuleForUnloading(oslModule) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_zeroMemory(void *, sal_Size) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_logfile_trace( const char*, ... ) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_logfile_longTrace(char const *, ...) { + std::abort(); +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL rtl_logfile_hasLogFile() { + for (;;) { std::abort(); } // avoid "must return a value" warnings +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/debugbase.cxx b/sal/osl/all/debugbase.cxx new file mode 100644 index 000000000..59848a883 --- /dev/null +++ b/sal/osl/all/debugbase.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 . + */ + +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <osl/process.h> +#include <osl/diagnose.hxx> +#include <sal/log.hxx> +#include <o3tl/string_view.hxx> + +#include <algorithm> +#include <vector> + +namespace { + +struct StaticDebugBaseAddressFilter + : rtl::StaticWithInit<std::vector<OString>, StaticDebugBaseAddressFilter> { + std::vector<OString> operator()() const { + std::vector<OString> vec; + rtl_uString * pStr = nullptr; + OUString const name( + "OSL_DEBUGBASE_STORE_ADDRESSES" ); + if (osl_getEnvironment( name.pData, &pStr ) == osl_Process_E_None) { + OUString const str(pStr); + rtl_uString_release(pStr); + sal_Int32 nIndex = 0; + do { + vec.push_back( OUStringToOString( + o3tl::getToken(str, 0, ';', nIndex ), + RTL_TEXTENCODING_ASCII_US ) ); + } + while (nIndex >= 0); + } + return vec; + } +}; + +bool isSubStr( char const* pStr, OString const& subStr ) +{ + return rtl_str_indexOfStr( pStr, subStr.getStr() ) >= 0; +} + +} // anon namespace + +extern "C" { + +// These functions presumably should not be extern "C", but changing +// that would break binary compatibility. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +#endif + +osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex() + SAL_THROW_EXTERN_C() +{ + static osl::Mutex aMutex; + return aMutex; +} +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName ) + SAL_THROW_EXTERN_C() +{ + std::vector<OString> const& rVec = StaticDebugBaseAddressFilter::get(); + if (rVec.empty()) + return false; + // check for "all": + OString const& rFirst = rVec[0]; + if ( rFirst == "all" ) + return true; + auto const iEnd( rVec.cend() ); + return std::any_of( rVec.begin(), iEnd, + [pName] (OString const& it) { return isSubStr(pName, it); }); +} + +bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount( + osl::detail::ObjectRegistryData const& rData, std::size_t nExpected ) + SAL_THROW_EXTERN_C() +{ + std::size_t nSize; + if (rData.m_bStoreAddresses) + nSize = rData.m_addresses.size(); + else + nSize = static_cast<std::size_t>(rData.m_nCount); + + bool const bRet = (nSize == nExpected); + SAL_WARN_IF( + !bRet, "sal.osl", + "unexpected number of " << rData.m_pName << ": " << nSize + << "; Expected: " << nExpected); + return bRet; +} + +void SAL_CALL osl_detail_ObjectRegistry_registerObject( + osl::detail::ObjectRegistryData & rData, void const* pObj ) + SAL_THROW_EXTERN_C() +{ + if (rData.m_bStoreAddresses) { + osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); + std::pair<osl::detail::VoidPointerSet::iterator, bool> const insertion( + rData.m_addresses.insert(pObj) ); + SAL_WARN_IF(!insertion.second, "sal.osl", "insertion failed!?"); + } + else { + osl_atomic_increment(&rData.m_nCount); + } +} + +void SAL_CALL osl_detail_ObjectRegistry_revokeObject( + osl::detail::ObjectRegistryData & rData, void const* pObj ) + SAL_THROW_EXTERN_C() +{ + if (rData.m_bStoreAddresses) { + osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); + std::size_t const n = rData.m_addresses.erase(pObj); + SAL_WARN_IF(n != 1, "sal.osl", "erased more than 1 entry!?"); + } + else { + osl_atomic_decrement(&rData.m_nCount); + } +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/filepath.cxx b/sal/osl/all/filepath.cxx new file mode 100644 index 000000000..afba01739 --- /dev/null +++ b/sal/osl/all/filepath.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 . + */ + +#include <osl/file.h> +#include <rtl/ustring.h> +#include <cassert> + +static sal_uInt32 osl_defCalcTextWidth( rtl_uString *ustrText ) +{ + return ustrText ? ustrText->length : 0; +} + +oslFileError SAL_CALL osl_abbreviateSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrCompacted, sal_uInt32 uMaxWidth, oslCalcTextWidthFunc pfnCalcWidth ) +{ + rtl_uString *ustrPath = nullptr; + rtl_uString *ustrFile = nullptr; + sal_uInt32 uPathWidth, uFileWidth; + + if ( !pfnCalcWidth ) + pfnCalcWidth = osl_defCalcTextWidth; + + { + sal_Int32 iLastSlash = rtl_ustr_lastIndexOfChar_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, SAL_PATHDELIMITER ); + + if ( iLastSlash >= 0 ) + { + rtl_uString_newFromStr_WithLength( &ustrPath, ustrSystemPath->buffer, iLastSlash ); + rtl_uString_newFromStr_WithLength( &ustrFile, &ustrSystemPath->buffer[iLastSlash], ustrSystemPath->length - iLastSlash ); + } + else + { + rtl_uString_new( &ustrPath ); + rtl_uString_newFromString( &ustrFile, ustrSystemPath ); + } + } + + assert(ustrPath && ustrFile); + + uPathWidth = pfnCalcWidth( ustrPath ); + uFileWidth = pfnCalcWidth( ustrFile ); + + /* First abbreviate the directory component of the path */ + + while ( uPathWidth + uFileWidth > uMaxWidth ) + { + if ( ustrPath->length > 3 ) + { + ustrPath->length--; + ustrPath->buffer[ustrPath->length-3] = '.'; + ustrPath->buffer[ustrPath->length-2] = '.'; + ustrPath->buffer[ustrPath->length-1] = '.'; + ustrPath->buffer[ustrPath->length] = 0; + + uPathWidth = pfnCalcWidth( ustrPath ); + } + else + break; + } + + /* Now abbreviate file component */ + + while ( uPathWidth + uFileWidth > uMaxWidth ) + { + if ( ustrFile->length > 4 ) + { + ustrFile->length--; + ustrFile->buffer[ustrFile->length-3] = '.'; + ustrFile->buffer[ustrFile->length-2] = '.'; + ustrFile->buffer[ustrFile->length-1] = '.'; + ustrFile->buffer[ustrFile->length] = 0; + + uFileWidth = pfnCalcWidth( ustrFile ); + } + else + break; + } + + rtl_uString_newConcat( pustrCompacted, ustrPath, ustrFile ); + + /* Event now if path was compacted to ".../..." it can be too large */ + + uPathWidth += uFileWidth; + + while ( uPathWidth > uMaxWidth ) + { + (*pustrCompacted)->length--; + (*pustrCompacted)->buffer[(*pustrCompacted)->length] = 0; + uPathWidth = pfnCalcWidth( *pustrCompacted ); + } + + rtl_uString_release(ustrPath); + rtl_uString_release(ustrFile); + + return osl_File_E_None; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/loadmodulerelative.cxx b/sal/osl/all/loadmodulerelative.cxx new file mode 100644 index 000000000..242bb6210 --- /dev/null +++ b/sal/osl/all/loadmodulerelative.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 . + */ + +#include <sal/config.h> + +#include <cstddef> + +#include <sal/log.hxx> +#include <osl/module.h> +#include <osl/module.hxx> +#include <rtl/malformeduriexception.hxx> +#include <rtl/uri.hxx> +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +extern "C" { + +#ifndef DISABLE_DYNLOADING + +oslModule SAL_CALL osl_loadModuleRelative( + oslGenericFunction const baseModule, rtl_uString * const relativePath, + sal_Int32 const mode) +{ + OUString base; + if (!osl::Module::getUrlFromAddress(baseModule, base)) { + SAL_INFO("sal.osl","osl::Module::getUrlFromAddress failed"); + return nullptr; + } + OUString abs; + try { + abs = rtl::Uri::convertRelToAbs(base, relativePath); + } catch (const rtl::MalformedUriException & e) { + SAL_INFO("sal.osl", "rtl::MalformedUriException <" << e.getMessage() << ">"); + return nullptr; + } + return osl_loadModule(abs.pData, mode); +} + +#endif // !DISABLE_DYNLOADING + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx new file mode 100644 index 000000000..405d5599c --- /dev/null +++ b/sal/osl/all/log.cxx @@ -0,0 +1,477 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <cassert> +#include <cstdarg> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <sstream> + +#include <stdio.h> +#include <string.h> +#include <fstream> + +#include <config_global.h> +#include <osl/thread.hxx> +#include <rtl/string.h> +#include <sal/detail/log.h> +#include <sal/log.hxx> +#include <sal/types.h> +#include <backtraceasstring.hxx> +#include <salusesyslog.hxx> + +#if defined ANDROID +#include <android/log.h> +#elif defined _WIN32 +#include <process.h> +#include <windows.h> +#define OSL_DETAIL_GETPID _getpid() +#else +#include <unistd.h> +#define OSL_DETAIL_GETPID getpid() +#endif + +#if HAVE_SYSLOG_H +#include <syslog.h> +// sal/osl/unx/salinit.cxx::sal_detail_initialize updates this: +bool sal_use_syslog; +#else +bool const sal_use_syslog = false; +#endif + +// Avoid the use of other sal code in this file as much as possible, so that +// this code can be called from other sal code without causing endless +// recursion. + +namespace { + +struct TimeContainer +{ + TimeValue aTime; + TimeContainer() + { + osl_getSystemTime(&aTime); + } +}; + +TimeContainer aStartTime; + +bool equalStrings( + char const * string1, std::size_t length1, char const * string2, + std::size_t length2) +{ + return length1 == length2 && std::memcmp(string1, string2, length1) == 0; +} + +#if !defined ANDROID +char const * toString(sal_detail_LogLevel level) { + switch (level) { + case SAL_DETAIL_LOG_LEVEL_INFO: + return "info"; + case SAL_DETAIL_LOG_LEVEL_WARN: + return "warn"; + case SAL_DETAIL_LOG_LEVEL_DEBUG: + return "debug"; + default: + assert(false); // this cannot happen + return "broken"; + } +} +#endif + +#ifdef _WIN32 + +char const* setEnvFromLoggingIniFile(const char* env, const char* key) +{ + char const* sResult = nullptr; + wchar_t buffer[MAX_PATH]; + GetModuleFileNameW(nullptr, buffer, MAX_PATH); + std::wstring sProgramDirectory(buffer); + std::wstring::size_type pos = sProgramDirectory.find_last_of(L"\\/"); + sProgramDirectory = sProgramDirectory.substr(0, pos+1); + sProgramDirectory += L"logging.ini"; + + std::ifstream logFileStream(sProgramDirectory); + if (!logFileStream.good()) + return sResult; + + std::size_t n; + std::string aKey; + std::string sWantedKey(key); + std::string sLine; + while (std::getline(logFileStream, sLine)) { + if (sLine.find('#') == 0) + continue; + if ( ( n = sLine.find('=') ) != std::string::npos) { + aKey = sLine.substr(0, n); + if (aKey != sWantedKey) + continue; + _putenv_s(env, sLine.substr(n+1, sLine.length()).c_str()); + sResult = std::getenv(env); + break; + } + } + return sResult; +} +#endif + +char const* pLogSelector = nullptr; + +char const* getLogLevelEnvVar() { + static char const* const pLevel = [] { + char const* pResult = nullptr; + + // First check the environment variable, then the setting in logging.ini + char const* env = std::getenv("SAL_LOG"); + +#ifdef _WIN32 + if (!env) + env = setEnvFromLoggingIniFile("SAL_LOG", "LogLevel"); +#endif + + if (env) + { + // Make a copy from the string in environment block + static std::string sLevel(env); + pResult = sLevel.c_str(); + } + return pResult; + }(); + + return pLevel; +} + +#if !defined ANDROID + +std::ofstream * getLogFile() { + static std::ofstream* const pFile = [] { + std::ofstream* pResult = nullptr; + + // First check the environment variable, then the setting in logging.ini + char const* logFile = std::getenv("SAL_LOG_FILE"); + +#ifdef _WIN32 + if (!logFile) + logFile = setEnvFromLoggingIniFile("SAL_LOG_FILE", "LogFilePath"); +#endif + + if (logFile) + { + // stays until process exits + static std::ofstream file(logFile, std::ios::app | std::ios::out); + pResult = &file; + } + + return pResult; + }(); + + return pFile; +} + + +std::pair<bool, bool> getTimestampFlags(char const *selector) +{ + bool outputTimestamp = false; + bool outputRelativeTimer = false; + for (char const* p = selector; p && *p;) + { + if (*p++ == '+') + { + char const * p1 = p; + while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') { + ++p1; + } + if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP"))) + outputTimestamp = true; + else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER"))) + outputRelativeTimer = true; + char const * p2 = p1; + while (*p2 != '+' && *p2 != '-' && *p2 != '\0') { + ++p2; + } + p = p2; + } + } + return std::pair(outputTimestamp, outputRelativeTimer); +} + +void maybeOutputTimestamp(std::ostringstream &s) { + static const std::pair<bool, bool> aEnvFlags = getTimestampFlags(getLogLevelEnvVar()); + const auto& [outputTimestamp, outputRelativeTimer] = (pLogSelector == nullptr ? aEnvFlags : getTimestampFlags(pLogSelector)); + + if (outputTimestamp) + { + char ts[100]; + TimeValue systemTime; + osl_getSystemTime(&systemTime); + TimeValue localTime; + osl_getLocalTimeFromSystemTime(&systemTime, &localTime); + oslDateTime dateTime; + osl_getDateTimeFromTimeValue(&localTime, &dateTime); + struct tm tm; + tm.tm_sec = dateTime.Seconds; + tm.tm_min = dateTime.Minutes; + tm.tm_hour = dateTime.Hours; + tm.tm_mday = dateTime.Day; + tm.tm_wday = dateTime.DayOfWeek; + tm.tm_mon = dateTime.Month - 1; + tm.tm_year = dateTime.Year - 1900; + tm.tm_yday = 0; + strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm); + char milliSecs[11]; + snprintf(milliSecs, sizeof(milliSecs), "%03u", + static_cast<unsigned>(dateTime.NanoSeconds / 1000000)); + s << ts << '.' << milliSecs << ':'; + } + if (!outputRelativeTimer) + return; + + TimeValue now; + osl_getSystemTime(&now); + int seconds = now.Seconds - aStartTime.aTime.Seconds; + int milliSeconds; + if (now.Nanosec < aStartTime.aTime.Nanosec) + { + seconds--; + milliSeconds = 1000 - (aStartTime.aTime.Nanosec - now.Nanosec) / 1000000; + } + else + milliSeconds = (now.Nanosec - aStartTime.aTime.Nanosec) / 1000000; + char relativeTimestamp[100]; + snprintf(relativeTimestamp, sizeof(relativeTimestamp), "%d.%03d", seconds, milliSeconds); + s << relativeTimestamp << ':'; +} + +#endif + +} + +void sal_detail_log( + sal_detail_LogLevel level, char const * area, char const * where, + char const * message, sal_uInt32 backtraceDepth) +{ + std::ostringstream s; +#if !defined ANDROID + // On Android, the area will be used as the "tag," and log info already + // contains timestamp and PID. + if (!sal_use_syslog) { + maybeOutputTimestamp(s); + s << toString(level) << ':'; + } + if (level != SAL_DETAIL_LOG_LEVEL_DEBUG) { + s << area << ':'; + } + s << OSL_DETAIL_GETPID << ':'; +#endif + s << osl::Thread::getCurrentIdentifier() << ':'; + if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) { + s << ' '; + } else { + const size_t nStrLen(std::strlen(SRCDIR "/")); + s << (where + + (std::strncmp(where, SRCDIR "/", nStrLen) == 0 + ? nStrLen : 0)); + } + s << message; + if (backtraceDepth != 0) { + s << " at:\n" << osl::detail::backtraceAsString(backtraceDepth); + } + +#if defined ANDROID + int android_log_level; + switch (level) { + case SAL_DETAIL_LOG_LEVEL_INFO: + android_log_level = ANDROID_LOG_INFO; + break; + case SAL_DETAIL_LOG_LEVEL_WARN: + android_log_level = ANDROID_LOG_WARN; + break; + case SAL_DETAIL_LOG_LEVEL_DEBUG: + android_log_level = ANDROID_LOG_DEBUG; + break; + default: + android_log_level = ANDROID_LOG_INFO; + break; + } + __android_log_print( + android_log_level, area == 0 ? "LibreOffice" : area, "%s", + s.str().c_str()); +#else + if (sal_use_syslog) { +#if HAVE_SYSLOG_H + int prio; + switch (level) { + case SAL_DETAIL_LOG_LEVEL_INFO: + prio = LOG_INFO; + break; + case SAL_DETAIL_LOG_LEVEL_WARN: + prio = LOG_WARNING; + break; + case SAL_DETAIL_LOG_LEVEL_DEBUG: + prio = LOG_DEBUG; + break; + default: + assert(false); // this cannot happen + prio = LOG_WARNING; + } + syslog(prio, "%s", s.str().c_str()); +#endif + } else { + // avoid calling getLogFile() more than once + static std::ofstream * logFile = getLogFile(); + if (logFile) { + *logFile << s.str() << std::endl; + } + else { + s << '\n'; +#ifdef _WIN32 + // write to Windows debugger console, too + OutputDebugStringA(s.str().c_str()); +#endif + std::fputs(s.str().c_str(), stderr); + std::fflush(stderr); + } + } +#endif +} + +void sal_detail_set_log_selector(char const *logSelector) +{ + pLogSelector = logSelector; +} + +void sal_detail_logFormat( + sal_detail_LogLevel level, char const * area, char const * where, + char const * format, ...) +{ + const sal_detail_LogAction eAction + = static_cast<sal_detail_LogAction>(sal_detail_log_report(level, area)); + if (eAction == SAL_DETAIL_LOG_ACTION_IGNORE) + return; + + std::va_list args; + va_start(args, format); + char buf[1024]; + int const len = sizeof buf - RTL_CONSTASCII_LENGTH("..."); + int n = vsnprintf(buf, len, format, args); + if (n < 0) { + std::strcpy(buf, "???"); + } else if (n >= len) { + std::strcpy(buf + len - 1, "..."); + } + sal_detail_log(level, area, where, buf, 0); + va_end(args); + + if (eAction == SAL_DETAIL_LOG_ACTION_FATAL) + std::abort(); +} + +unsigned char sal_detail_log_report(sal_detail_LogLevel level, char const * area) +{ + if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) { + return SAL_DETAIL_LOG_ACTION_LOG; + } + assert(area != nullptr); + static char const* const envEnv = [] { + char const* pResult = getLogLevelEnvVar(); + if (!pResult) + pResult = "+WARN"; + return pResult; + }(); + char const* const env = (pLogSelector == nullptr ? envEnv : pLogSelector); + std::size_t areaLen = std::strlen(area); + enum Sense { POSITIVE = 0, NEGATIVE = 1 }; + std::size_t senseLen[2] = { 0, 1 }; + // initial senseLen[POSITIVE] < senseLen[NEGATIVE], so that if there are + // no matching switches at all, the result will be negative (and + // initializing with 1 is safe as the length of a valid switch, even + // without the "+"/"-" prefix, will always be > 1) + bool senseFatal[2] = { false, false }; + bool seenWarn = false; + bool bFlagFatal = false; + for (char const * p = env;;) { + Sense sense; + switch (*p++) { + case '\0': + { + if (level == SAL_DETAIL_LOG_LEVEL_WARN && !seenWarn) + return sal_detail_log_report(SAL_DETAIL_LOG_LEVEL_INFO, area); + + sal_detail_LogAction eAction = SAL_DETAIL_LOG_ACTION_IGNORE; + // if a specific item is positive and negative (==), default to positive + if (senseLen[POSITIVE] >= senseLen[NEGATIVE]) + { + if (senseFatal[POSITIVE]) eAction = SAL_DETAIL_LOG_ACTION_FATAL; + else eAction = SAL_DETAIL_LOG_ACTION_LOG; + } + return eAction; + } + case '+': + sense = POSITIVE; + break; + case '-': + sense = NEGATIVE; + break; + default: + return SAL_DETAIL_LOG_ACTION_LOG; // upon an illegal SAL_LOG value, enable everything + } + char const * p1 = p; + while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') { + ++p1; + } + bool match; + if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("INFO"))) { + match = level == SAL_DETAIL_LOG_LEVEL_INFO; + } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN"))) + { + match = level == SAL_DETAIL_LOG_LEVEL_WARN; + seenWarn = true; + } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("FATAL"))) + { + bFlagFatal = (sense == POSITIVE); + match = false; + } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")) || + equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER"))) + { + // handled later + match = false; + } else { + return SAL_DETAIL_LOG_ACTION_LOG; + // upon an illegal SAL_LOG value, everything is considered + // positive + } + char const * p2 = p1; + while (*p2 != '+' && *p2 != '-' && *p2 != '\0') { + ++p2; + } + if (match) { + if (*p1 == '.') { + ++p1; + std::size_t n = p2 - p1; + if ((n == areaLen && equalStrings(p1, n, area, areaLen)) + || (n < areaLen && area[n] == '.' + && equalStrings(p1, n, area, n))) + { + senseLen[sense] = p2 - p; + senseFatal[sense] = bFlagFatal; + } + } else { + senseLen[sense] = p1 - p; + senseFatal[sense] = bFlagFatal; + } + } + p = p2; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/mutexshared.cxx b/sal/osl/all/mutexshared.cxx new file mode 100644 index 000000000..3de7f9930 --- /dev/null +++ b/sal/osl/all/mutexshared.cxx @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <osl/mutex.hxx> + +oslMutex* SAL_CALL osl_getGlobalMutex() +{ + static osl::Mutex g_Mutex; + return &g_Mutex.mutex; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/osl/all/signalshared.cxx b/sal/osl/all/signalshared.cxx new file mode 100644 index 000000000..530413f26 --- /dev/null +++ b/sal/osl/all/signalshared.cxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 . + */ + +#include <sal/config.h> + +#include <stdlib.h> + +#include <signalshared.hxx> + +#include <osl/diagnose.h> +#include <mutex> + +namespace +{ +oslSignalHandlerImpl* SignalList; +bool bInitSignal = false; + +std::mutex& getSignalMutex() +{ + static std::mutex aMutex; + return aMutex; +} +} + +oslSignalAction callSignalHandler(oslSignalInfo* pInfo) +{ + oslSignalHandlerImpl* pHandler = SignalList; + oslSignalAction Action = osl_Signal_ActCallNextHdl; + + while (pHandler) + { + if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl) + break; + + pHandler = pHandler->pNext; + } + + return Action; +} + +oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction handler, void* pData) +{ + if (!handler) + return nullptr; + + oslSignalHandlerImpl* pHandler + = static_cast<oslSignalHandlerImpl*>(calloc(1, sizeof(oslSignalHandlerImpl))); + + std::scoped_lock aGuard(getSignalMutex()); + + if (!bInitSignal) + bInitSignal = onInitSignal(); + + if (pHandler) + { + pHandler->Handler = handler; + pHandler->pData = pData; + + pHandler->pNext = SignalList; + SignalList = pHandler; + + return pHandler; + } + + return nullptr; +} + +sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler handler) +{ + std::scoped_lock aGuard(getSignalMutex()); + + if (!bInitSignal) + bInitSignal = onInitSignal(); + + oslSignalHandlerImpl* pHandler = SignalList; + oslSignalHandlerImpl* pPrevious = nullptr; + + while (pHandler) + { + if (pHandler == handler) + { + if (pPrevious) + pPrevious->pNext = pHandler->pNext; + else + SignalList = pHandler->pNext; + + if (SignalList == nullptr) + bInitSignal = onDeInitSignal(); + + free(pHandler); + + return true; + } + + pPrevious = pHandler; + pHandler = pHandler->pNext; + } + + return false; +} + +oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 userSignal, void* userData) +{ + std::scoped_lock aGuard(getSignalMutex()); + + if (!bInitSignal) + bInitSignal = onInitSignal(); + + oslSignalInfo info; + info.Signal = osl_Signal_User; + info.UserSignal = userSignal; + info.UserData = userData; + + oslSignalAction action = callSignalHandler(&info); + + return action; +} + +sal_Bool SAL_CALL osl_setErrorReporting(sal_Bool /*bEnable*/) +{ + // this is part of the stable API + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/all/utility.cxx b/sal/osl/all/utility.cxx new file mode 100644 index 000000000..e22bdd3de --- /dev/null +++ b/sal/osl/all/utility.cxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 . + */ + +#include <osl/time.h> + +/* + * mfe : maybe it would be wishful to include initialization + * of the global timer in dllmain or _init directly. + * But nonetheless this (should) work too. + */ +namespace osl +{ + +namespace { + +class OGlobalTimer +{ + +public: + + OGlobalTimer() { + osl_getGlobalTimer(); + } + +}; + +} + +static OGlobalTimer aGlobalTimer; + +} // namespace osl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |