diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2011-11-22 09:34:46 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2011-11-22 09:41:47 +0100 |
commit | 70a6b9ffbd676a1384433a86205d2cd4f2d4f4b1 (patch) | |
tree | ffb31ef817b5f2037cf7c332da422b9179d613d5 /sal/inc | |
parent | f2972242673cc9608960e9ca70e82766be5275e3 (diff) |
New sal/log.h obsoletes osl/diagnose.h and tools/debug.hxx.
* New SAL_INFO..., SAL_WARN... macros.
* New SAL_STREAM supersedes OSL_FORMAT.
* oustringostreaminserter.hxx moved from unotest to rtl (and always UTF-8 now).
* TODO to enable GCC __attribute__((format)) in sal/log.h (requires call-site
cleanup).
* Further functionality in tools/debug.hxx (DBG_MEMTEST, DBG_CTOR, etc.) not yet
addressed.
* Some replacements tools String -> rtl::OUString.
Diffstat (limited to 'sal/inc')
-rw-r--r-- | sal/inc/osl/diagnose.h | 79 | ||||
-rw-r--r-- | sal/inc/osl/diagnose.hxx | 27 | ||||
-rw-r--r-- | sal/inc/osl/thread.hxx | 10 | ||||
-rw-r--r-- | sal/inc/rtl/oustringostreaminserter.hxx | 61 | ||||
-rw-r--r-- | sal/inc/rtl/strbuf.hxx | 11 | ||||
-rw-r--r-- | sal/inc/rtl/string.hxx | 19 | ||||
-rw-r--r-- | sal/inc/rtl/ustrbuf.hxx | 15 | ||||
-rw-r--r-- | sal/inc/rtl/ustring.hxx | 29 | ||||
-rw-r--r-- | sal/inc/sal/log.h | 305 |
9 files changed, 455 insertions, 101 deletions
diff --git a/sal/inc/osl/diagnose.h b/sal/inc/osl/diagnose.h index aab76b320f2a..8e889ac5a37a 100644 --- a/sal/inc/osl/diagnose.h +++ b/sal/inc/osl/diagnose.h @@ -30,10 +30,25 @@ #ifndef _OSL_DIAGNOSE_H_ #define _OSL_DIAGNOSE_H_ +#include "sal/config.h" + +#include <sal/log.h> #include <sal/types.h> /** provides simple diagnostic support + The facilities provided by this header are deprecated. True assertions + (that detect broken program logic) should use standard assert (which aborts + if an assertion fails, and is controlled by the standard NDEBUG macro). + Logging of warnings (e.g., about malformed input) and traces (e.g., about + steps taken while executing some protocol) should use the facilities + provided by sal/log.h. + + Because the assertion macros (OSL_ASSERT, OSL_ENSURE, OSL_FAIL, OSL_PRECOND, + and OSL_POSTCOND) have been used for true assertions as well as for logged + warnings, they map to SAL_WARN instead of standard assert. OSL_TRACE maps + to SAL_INFO. + The functions defined in this header are not intended to be used directly, but through defined macros. The macros can be divided into three categories: assertions, traces and other stuff .-) Their usability depends on the value @@ -122,14 +137,25 @@ pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc( pf #define OSL_THIS_FILE __FILE__ -/* the macro OSL_LOG_PREFIX is intended to be an office internal macro for now */ -#define OSL_LOG_PREFIX OSL_THIS_FILE ":" SAL_STRINGIFY( __LINE__ ) "; " +/* the macro OSL_LOG_PREFIX is intended to be an office internal macro for now + + it is deprecated and superseded by SAL_WHERE +*/ +#define OSL_LOG_PREFIX SAL_WHERE #define OSL_DEBUG_ONLY(s) _OSL_DEBUG_ONLY(s) -#define OSL_TRACE _OSL_TRACE -#define OSL_ASSERT(c) _OSL_ENSURE(c, OSL_THIS_FILE, __LINE__, 0) -#define OSL_ENSURE(c, m) _OSL_ENSURE(c, OSL_THIS_FILE, __LINE__, m) -#define OSL_FAIL(m) _OSL_ENSURE(0, OSL_THIS_FILE, __LINE__, m) + +#if OSL_DEBUG_LEVEL > 0 +#define OSL_TRACE(...) SAL_INFO("legacy.osl", __VA_ARGS__) +#define OSL_ASSERT(c) SAL_WARN_IF(!(c), "legacy.osl", "OSL_ASSERT") +#define OSL_ENSURE(c, m) SAL_WARN_IF(!(c), "legacy.osl", "%s", m) +#define OSL_FAIL(m) SAL_WARN_IF(sal_True, "legacy.osl", "%s", m) +#else +#define OSL_TRACE(...) ((void) 0) +#define OSL_ASSERT(c) ((void) 0) +#define OSL_ENSURE(c, m) ((void) 0) +#define OSL_FAIL(m) ((void) 0) +#endif #define OSL_VERIFY(c) do { if (!(c)) OSL_ASSERT(0); } while (0) #define OSL_PRECOND(c, m) OSL_ENSURE(c, m) @@ -145,27 +171,10 @@ pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc( pf #if OSL_DEBUG_LEVEL > 0 #define _OSL_DEBUG_ONLY(f) (f) -#define _OSL_ENSURE(c, f, l, m) \ - do \ - { \ - if (!(c) && _OSL_GLOBAL osl_assertFailedLine(f, l, m)) \ - _OSL_GLOBAL osl_breakDebug(); \ - } while (0) #else #define _OSL_DEBUG_ONLY(f) ((void)0) -#define _OSL_ENSURE(c, f, l, m) ((void)0) - -#endif /* OSL_DEBUG_LEVEL */ - -#if OSL_DEBUG_LEVEL > 1 - -#define _OSL_TRACE _OSL_GLOBAL osl_trace - -#else - -#define _OSL_TRACE 1 ? ((void)0) : _OSL_GLOBAL osl_trace #endif /* OSL_DEBUG_LEVEL */ @@ -192,30 +201,6 @@ pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc( pf #define OSL_THIS_FUNC "" #endif -#if defined __cplusplus - -#include "rtl/string.hxx" - -/** @internal */ -extern "C" struct _rtl_String * SAL_CALL osl_detail_formatString( - char const * format, ...) SAL_THROW_EXTERN_C(); - // "struct _rtl_String" instead of "rtl_String" for the case where - // osl/diagnose.h is included in rtl/string.hxx - -/** A facility for printf-style messages in OSL_ENSURE, OSL_FAIL, etc. - - Use like: OSL_ENSURE(i == 5, OSL_FORMAT("i should be 5 but is %d", i)); -*/ -#define OSL_FORMAT(format, ...) \ - (::rtl::OString( \ - ::osl_detail_formatString(format, __VA_ARGS__), \ - ::SAL_NO_ACQUIRE).getStr()) - // it appears that all relevant compilers (esp. GCC 4.0 and MS VS 2008 - // Express) already support variadic macros in C++; see also - // <http://wiki.apache.org/stdcxx/C++0xCompilerSupport> - -#endif - #endif /* _OSL_DIAGNOSE_H_ */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/osl/diagnose.hxx b/sal/inc/osl/diagnose.hxx index a9aba130d72b..42e4b8dd7f2f 100644 --- a/sal/inc/osl/diagnose.hxx +++ b/sal/inc/osl/diagnose.hxx @@ -25,27 +25,22 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#if ! defined(OSL_DIAGNOSE_HXX_INCLUDED) +#ifndef OSL_DIAGNOSE_HXX_INCLUDED #define OSL_DIAGNOSE_HXX_INCLUDED -#if ! defined(_OSL_DIAGNOSE_H_) +#include "sal/config.h" + +#include <functional> +#include <typeinfo> + +#include "boost/unordered_set.hpp" #include "osl/diagnose.h" -#endif -#if ! defined(_OSL_INTERLOCK_H_) #include "osl/interlck.h" -#endif -#if ! defined(_OSL_MUTEX_HXX_) #include "osl/mutex.hxx" -#endif -#if ! defined(INCLUDED_RTL_ALLOCATOR_HXX) #include "rtl/allocator.hxx" -#endif -#if ! defined(_RTL_INSTANCE_HXX_) #include "rtl/instance.hxx" -#endif -#include <boost/unordered_set.hpp> -#include <functional> -#include <typeinfo> +#include "sal/log.h" +#include "sal/types.h" namespace osl { /// @internal @@ -126,7 +121,7 @@ public: VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin()); VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end()); for ( ; iPos != iEnd; ++iPos ) { - OSL_ASSERT( *iPos != 0 ); + SAL_WARN_IF( *iPos == 0, "sal.debug", "null pointer" ); } } return bRet; @@ -179,7 +174,7 @@ public: static bool checkObjectCount( ::std::size_t = 0 ) { return true; } #else // OSL_DEBUG_LEVEL > 0 /** @return whether the expected number of objects is alive, - else this function OSL_ASSERTs + else this function SAL_WARNs */ static bool checkObjectCount( ::std::size_t nExpected = 0 ) { return StaticObjectRegistry::get().checkObjectCount(nExpected); diff --git a/sal/inc/osl/thread.hxx b/sal/inc/osl/thread.hxx index 2bcc82fd07eb..2916ff7443d6 100644 --- a/sal/inc/osl/thread.hxx +++ b/sal/inc/osl/thread.hxx @@ -29,7 +29,9 @@ #ifndef _THREAD_HXX_ #define _THREAD_HXX_ -#ifdef __cplusplus +#include "sal/config.h" + +#include <cassert> #include <osl/time.h> @@ -71,7 +73,7 @@ public: sal_Bool SAL_CALL create() { - OSL_ASSERT(m_hThread == 0); // only one running thread per instance + assert(m_hThread == 0); // only one running thread per instance if (m_hThread) return sal_False; @@ -84,7 +86,7 @@ public: sal_Bool SAL_CALL createSuspended() { - OSL_ASSERT(m_hThread == 0); // only one running thread per instance + assert(m_hThread == 0); // only one running thread per instance if( m_hThread) return sal_False; m_hThread= osl_createSuspendedThread( threadFunc, @@ -233,7 +235,7 @@ private: }; } // end namespace osl -#endif + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/rtl/oustringostreaminserter.hxx b/sal/inc/rtl/oustringostreaminserter.hxx new file mode 100644 index 000000000000..579ffa0cd045 --- /dev/null +++ b/sal/inc/rtl/oustringostreaminserter.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef INCLUDED_RTL_OUSTRINGOSTREAMINSERTER_HXX +#define INCLUDED_RTL_OUSTRINGOSTREAMINSERTER_HXX + +#include "sal/config.h" + +#include <ostream> + +#include "rtl/textenc.h" +#include "rtl/ustring.hxx" + +/** Include this header to support rtl::OUString in std::ostream (and thus in + CPPUNIT_ASSERT macros, for example). + + The rtl::OUString is converted to UTF-8. + + @since LibreOffice 3.5. +*/ + +namespace rtl { + +template< typename charT, typename traits > std::basic_ostream<charT, traits> & +operator <<( + std::basic_ostream<charT, traits> & stream, rtl::OUString const & string) +{ + return stream << + rtl::OUStringToOString(string, RTL_TEXTENCODING_UTF8).getStr(); + // best effort; potentially loses data due to conversion failures + // (stray surrogate halves) and embedded null characters +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/rtl/strbuf.hxx b/sal/inc/rtl/strbuf.hxx index 962d3dfda8a0..5f0b9b3fecc0 100644 --- a/sal/inc/rtl/strbuf.hxx +++ b/sal/inc/rtl/strbuf.hxx @@ -29,7 +29,10 @@ #ifndef _RTL_STRBUF_HXX_ #define _RTL_STRBUF_HXX_ -#include "osl/diagnose.h" +#include "sal/config.h" + +#include <cassert> + #include <rtl/strbuf.h> #include <rtl/string.hxx> @@ -253,7 +256,7 @@ public: */ void setLength(sal_Int32 newLength) { - OSL_ASSERT(newLength >= 0); + assert(newLength >= 0); // Avoid modifications if pData points to const empty string: if( newLength != pData->length ) { @@ -280,7 +283,7 @@ public: */ sal_Char charAt( sal_Int32 index ) { - OSL_ASSERT(index >= 0 && index < pData->length); + assert(index >= 0 && index < pData->length); return pData->buffer[ index ]; } @@ -321,7 +324,7 @@ public: */ OStringBuffer & setCharAt(sal_Int32 index, sal_Char ch) { - OSL_ASSERT(index >= 0 && index < pData->length); + assert(index >= 0 && index < pData->length); pData->buffer[ index ] = ch; return *this; } diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx index ee4101188013..007129a7dc0f 100644 --- a/sal/inc/rtl/string.hxx +++ b/sal/inc/rtl/string.hxx @@ -29,12 +29,15 @@ #ifndef _RTL_STRING_HXX_ #define _RTL_STRING_HXX_ -#ifdef __cplusplus +#include "sal/config.h" + +#include <cassert> #include <osl/diagnose.h> #include <rtl/memory.h> #include <rtl/textenc.h> #include <rtl/string.h> +#include "sal/log.h" #if !defined EXCEPTIONS_OFF #include <new> @@ -183,13 +186,13 @@ public: { pData = 0; rtl_uString2String( &pData, value, length, encoding, convertFlags ); + if (pData == 0) { #if defined EXCEPTIONS_OFF - OSL_ASSERT(pData != NULL); + SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF"); #else - if (pData == 0) { throw std::bad_alloc(); - } #endif + } } /** @@ -655,7 +658,7 @@ public: */ OString copy( sal_Int32 beginIndex ) const SAL_THROW(()) { - OSL_ASSERT(beginIndex >= 0 && beginIndex <= getLength()); + assert(beginIndex >= 0 && beginIndex <= getLength()); if ( beginIndex == 0 ) return *this; else @@ -679,8 +682,8 @@ public: */ OString copy( sal_Int32 beginIndex, sal_Int32 count ) const SAL_THROW(()) { - OSL_ASSERT(beginIndex >= 0 && beginIndex <= getLength() - && count >= 0 && count <= getLength() - beginIndex); + assert(beginIndex >= 0 && beginIndex <= getLength() + && count >= 0 && count <= getLength() - beginIndex); if ( (beginIndex == 0) && (count == getLength()) ) return *this; else @@ -1034,8 +1037,6 @@ struct OStringHash } /* Namespace */ -#endif /* __cplusplus */ - #endif /* _RTL_STRING_HXX_ */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/rtl/ustrbuf.hxx b/sal/inc/rtl/ustrbuf.hxx index 60bb750a1dc7..2456316274d2 100644 --- a/sal/inc/rtl/ustrbuf.hxx +++ b/sal/inc/rtl/ustrbuf.hxx @@ -29,12 +29,14 @@ #ifndef _RTL_USTRBUF_HXX_ #define _RTL_USTRBUF_HXX_ +#include "sal/config.h" + +#include <cassert> + #include <osl/diagnose.h> #include <rtl/ustrbuf.h> #include <rtl/ustring.hxx> -#ifdef __cplusplus - namespace rtl { @@ -233,7 +235,7 @@ public: */ void setLength(sal_Int32 newLength) { - OSL_ASSERT(newLength >= 0); + assert(newLength >= 0); // Avoid modifications if pData points to const empty string: if( newLength != pData->length ) { @@ -260,7 +262,7 @@ public: */ sal_Unicode charAt( sal_Int32 index ) const { - OSL_ASSERT(index >= 0 && index < pData->length); + assert(index >= 0 && index < pData->length); return pData->buffer[ index ]; } @@ -301,7 +303,7 @@ public: */ OUStringBuffer & setCharAt(sal_Int32 index, sal_Unicode ch) { - OSL_ASSERT(index >= 0 && index < pData->length); + assert(index >= 0 && index < pData->length); pData->buffer[ index ] = ch; return *this; } @@ -434,7 +436,7 @@ public: */ OUStringBuffer & append(char c) { - OSL_ASSERT(static_cast< unsigned char >(c) <= 0x7F); + assert(static_cast< unsigned char >(c) <= 0x7F); return append(sal_Unicode(c)); } @@ -819,7 +821,6 @@ private: } -#endif /* __cplusplus */ #endif /* _RTL_USTRBUF_HXX_ */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx index edf7c9747962..ef13dd1da387 100644 --- a/sal/inc/rtl/ustring.hxx +++ b/sal/inc/rtl/ustring.hxx @@ -29,12 +29,15 @@ #ifndef _RTL_USTRING_HXX_ #define _RTL_USTRING_HXX_ -#ifdef __cplusplus +#include "sal/config.h" + +#include <cassert> #include "osl/diagnose.h" #include <rtl/ustring.h> #include <rtl/string.hxx> #include <rtl/memory.h> +#include "sal/log.h" #if defined EXCEPTIONS_OFF #include <stdlib.h> @@ -184,13 +187,13 @@ public: { pData = 0; rtl_string2UString( &pData, value, length, encoding, convertFlags ); + if (pData == 0) { #if defined EXCEPTIONS_OFF - OSL_ASSERT(pData != NULL); + SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF"); #else - if (pData == 0) { throw std::bad_alloc(); - } #endif + } } /** Create a new string from an array of Unicode code points. @@ -967,7 +970,7 @@ public: */ OUString copy( sal_Int32 beginIndex ) const SAL_THROW(()) { - OSL_ASSERT(beginIndex >= 0 && beginIndex <= getLength()); + assert(beginIndex >= 0 && beginIndex <= getLength()); if ( beginIndex == 0 ) return *this; else @@ -991,7 +994,7 @@ public: */ OUString copy( sal_Int32 beginIndex, sal_Int32 count ) const SAL_THROW(()) { - OSL_ASSERT(beginIndex >= 0 && beginIndex <= getLength() && count >= 0); + assert(beginIndex >= 0 && beginIndex <= getLength() && count >= 0); if ( (beginIndex == 0) && (count == getLength()) ) return *this; else @@ -1243,13 +1246,13 @@ public: { rtl_uString * pNew = 0; rtl_uString_intern( &pNew, pData ); + if (pNew == 0) { #if defined EXCEPTIONS_OFF - OSL_ASSERT(pNew != NULL); + SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF"); #else - if (pNew == 0) { throw std::bad_alloc(); - } #endif + } return OUString( pNew, (DO_NOT_ACQUIRE *)0 ); } @@ -1286,13 +1289,13 @@ public: rtl_uString * pNew = 0; rtl_uString_internConvert( &pNew, value, length, encoding, convertFlags, pInfo ); + if (pNew == 0) { #if defined EXCEPTIONS_OFF - OSL_ASSERT(pNew != NULL); + SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF"); #else - if (pNew == 0) { throw std::bad_alloc(); - } #endif + } return OUString( pNew, (DO_NOT_ACQUIRE *)0 ); } @@ -1576,8 +1579,6 @@ inline OString OUStringToOString( const OUString & rUnicode, } /* Namespace */ -#endif /* __cplusplus */ - #endif /* _RTL_USTRING_HXX */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/sal/log.h b/sal/inc/sal/log.h new file mode 100644 index 000000000000..9e15560aa2c1 --- /dev/null +++ b/sal/inc/sal/log.h @@ -0,0 +1,305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * [ Copyright (C) 2011 Stephan Bergmann, Red Hat <sbergman@redhat.com> (initial + * developer) ] + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_SAL_LOG_H +#define INCLUDED_SAL_LOG_H + +#include "sal/config.h" + +#if defined __cplusplus +#include <sstream> +#include <string> +#endif + +#include "sal/types.h" + +/* This header uses variadic macros in both C (where they are officially only + supported since C99) and C++ (where they are officially only supported since + C++11). It appears that all relevant compilers (esp. GCC 4.0 and MS VS 2008 + Express) already support them in their C and C++ dialects. See also + <http://wiki.apache.org/stdcxx/C++0xCompilerSupport>. + + Avoid the use of other sal code in this header as much as possible, so that + this code can be called from other sal code without causing endless + recursion. +*/ + +#if defined __cplusplus +extern "C" { +#endif + +/** @internal */ +enum sal_detail_LogLevel { + SAL_DETAIL_LOG_LEVEL_INFO, SAL_DETAIL_LOG_LEVEL_WARN, + SAL_DETAIL_MAKE_FIXED_SIZE = SAL_MAX_ENUM +}; + +/** @internal */ +void SAL_CALL sal_detail_log( + enum sal_detail_LogLevel level, char const * area, char const * where, + char const * message); + +/** @internal */ +void SAL_CALL sal_detail_logFormat( + enum sal_detail_LogLevel level, char const * area, char const * where, + char const * format, ...) +/* TODO: enabling this will produce a huge amount of -Werror=format errors: */ +#if defined GCC && 0 + __attribute__((format(printf, 4, 5))) +#endif + ; + +#if defined __cplusplus +} +#endif + +/** @internal */ +#define SAL_DETAIL_LOG_FORMAT(condition, level, area, where, ...) \ + do { \ + if (condition) { \ + sal_detail_logFormat((level), (area), (where), __VA_ARGS__); \ + } \ + } while (sal_False) + +#if defined __cplusplus + +namespace sal { namespace detail { + +/// @internal +inline void SAL_CALL log( + sal_detail_LogLevel level, char const * area, char const * where, + std::ostringstream const & stream) +{ + // An alternative would be to have sal_detail_log take a std::ostringstream + // pointer (via a C void pointer); the advantage would be smaller client + // code (the ".str().c_str()" part would move into the implementation of + // sal_detail_log) and potential for proper support of embedded null + // characters within the message, but the disadvantage would be dependence + // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved + // to this inline function so that it is potentially only emitted once per + // dynamic library: + sal_detail_log(level, area, where, stream.str().c_str()); +} + +} } + +/// @internal +#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \ + do { \ + if (condition) { \ + ::std::ostringstream sal_detail_stream; \ + sal_detail_stream << stream; \ + ::sal::detail::log((level), (area), (where), sal_detail_stream); \ + } \ + } while (false) + +#endif + +/** A simple macro to create a "file and line number" string. + + Potentially not only useful within the log framework (where it is used + automatically), but also when creating exception messages. + + @since LibreOffice 3.5 +*/ +#define SAL_WHERE __FILE__ ":" SAL_STRINGIFY(__LINE__) ": " + +#if defined __cplusplus + +/** A facility for generating temporary string messages by piping items into a + C++ std::ostringstream. + + This can be useful for example in a call to SAL_INFO_S when depending on + some boolean condition data of incompatible types shall be streamed into the + message, as in: + + SAL_INFO_S( + "foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj))); + + @since LibreOffice 3.5 +*/ +#define SAL_STREAM(stream) \ + (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream). \ + str()) + +#endif + +/** Basic logging functionality. + + SAL_INFO(char const * area, char const * format, ...), + SAL_INFO_IF(bool condition, char const * area, char const * format, ...), + SAL_WARN(char const * area, char const * format, ...), and + SAL_WARN_IF(bool condition, char const * area, char const * format, ...) + produce an info resp. warning log entry with a printf-style message. The + given format argument and any following arguments must be so that that + sequence of arguments would be appropriate for a call to printf. + + SAL_INFO_S(char const * area, expr), + SAL_INFO_IF_S(bool condition, char const * area, expr), + SAL_WARN_S(char const * area, expr), and + SAL_WARN_IF_S(bool condition, char const * area, expr) produce an info resp. + warning log entry with a message produced by piping items into a C++ + std::ostringstream (and are only available in C++). The given expr must be + so that the full expression "stream << expr" is valid, where stream is a + variable of type std::ostringstream. + + SAL_INFO_S("foo", "string " << s << " of length " << n) + + would be an example of such a call; if the given s is of type rtl::OUString, + + #include "rtl/oustringostreaminserter.hxx" + + would make sure that an appropriate operator << is available. + + In either case, the composed message should be in UTF-8 and it should + contain no vertical formatting characters and no null characters + + For the _IF variants, log output is only generated if the given condition is + true (in addition to the other conditions that have to be met). + + For all these macros, the given area argument must be non-null and must + match the regular expression + + <area> ::= <segment>("."<segment>)* + + with + + <segment> ::= [0-9a-z]+ + + Whether these macros generate any log output is controlled in a two-stage + process. + + First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN, + respectively, control whether the INFO and WARN macros, respectively, + expand to actual code (in case the macro is defined, to any value) or to + no-ops (in case the macro is not defined). + + Second, at runtime the environment variable SAL_LOG further limits which + macro calls actually generate log output. The environment variable SAL_LOG + must either be unset or must match the regular expression + + <env> ::= <switch>* + + with + + <switch> ::= <sense><level>("."<area>)? + <sense> ::= "+"|"-" + <level> ::= "INFO"|"WARN" + + If the environment variable is unset, "+WARN" is used instead (which results + in all warnings being output but no infos). If the given value does not + match the regular expression, "+INFO+WARN" is used instead (which in turn + results in everything being output). + + A given macro call's level (INFO or WARN) and area is matched against the + given switches as follows: Only those switches for which the level matches + the given level and for which the area is a prefix (including both empty and + full prefixes) of the given area are considered. Log output is generated if + and only if among the longest such switches (if any), there is at least one + that has a sense of "+". (That is, if both +INFO.foo and -INFO.foo are + present, +INFO.foo wins.) + + For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like + SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or + SAL_INFO("other", ...) generate output, while calls like + SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not. + + The generated log output consists of the given level ("info" or "warn"), the + given area, the process ID, the thread ID, the source file, and the source + line number, each followed by a colon, followed by a space, the given + message, and a newline. The precise format of the log output is subject to + change. The log output is printed to stderr without further text encoding + conversion. + + @since LibreOffice 3.5 +*/ + +#if defined SAL_LOG_INFO + +#define SAL_INFO(area, ...) \ + SAL_DETAIL_LOG_FORMAT( \ + sal_True, SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, __VA_ARGS__) +#define SAL_INFO_IF(condition, area, ...) \ + SAL_DETAIL_LOG_FORMAT( \ + condition, SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, __VA_ARGS__) + +#if defined __cplusplus +#define SAL_INFO_S(area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + true, ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream) +#define SAL_INFO_IF_S(condition, area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + condition, ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream) +#endif + +#else + +#define SAL_INFO(area, format, ...) ((void) 0) +#define SAL_INFO_IF(condition, area, format, ...) ((void) 0) + +#if defined __cplusplus +#define SAL_INFO_S(area, stream) ((void) 0) +#define SAL_INFO_IF_S(condition, area, stream) ((void) 0) +#endif + +#endif + +#if defined SAL_LOG_WARN + +#define SAL_WARN(area, ...) \ + SAL_DETAIL_LOG_FORMAT( \ + sal_True, SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, __VA_ARGS__) +#define SAL_WARN_IF(condition, area, ...) \ + SAL_DETAIL_LOG_FORMAT( \ + condition, SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, __VA_ARGS__) + +#if defined __cplusplus +#define SAL_WARN_S(area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + true, ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream) +#define SAL_WARN_IF_S(condition, area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + condition, ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream) +#endif + +#else + +#define SAL_WARN(area, format, ...) ((void) 0) +#define SAL_WARN_IF(condition, area, format, ...) ((void) 0) + +#if defined __cplusplus +#define SAL_WARN_S(area, stream) ((void) 0) +#define SAL_WARN_IF_S(condition, area, stream) ((void) 0) +#endif + +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |