// @configure_input@
// $Header$
//
// Copyright (C) 2000 - 2003, by
// 
// Carlo Wood, Run on IRC <carlo@alinoe.com>
// RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
//
// This file may be distributed under the terms of the Q Public License
// version 1.0 as appearing in the file LICENSE.QPL included in the
// packaging of this file.
//

/** \file libcwd/config.h
 * Do not include this header file directly, instead include "\ref preparation_step2 "debug.h"".
 */

#ifndef LIBCWD_CONFIG_H
#define LIBCWD_CONFIG_H

//
// DO NOT CHANGE THIS FILE
//
// The defines in this file are configuration options chosen during
// compilation of libcwd.  To change these options, run `configure'
// with the appropriate commandline options (Use `configure --help'
// for more details).  In order to be sure that a program is linking
// with a library that was compiled with the same header file, call
// Debug( check_configuration() ); at the top of main() in your program.
//

/**
 * \addtogroup group_configuration Configuration Options And Macros
 * \ingroup book_start
 *
 * Libcwd uses autoconf; configuration is done with the usual \shellcommand configure \endshellcommand script.&nbsp;
 * You can list all options of configure by issuing \shellcommand configure --help \endshellcommand.
 *
 * This section describes the configure options specific to libcwd.&nbsp;
 * The name of the macros that are related to the respective features are given between parenthesis after the option.&nbsp;
 * You can not define these macros yourself, you may only use them in an <CODE>\#if ... \#endif</CODE> test.&nbsp;
 * The macros are always defined; when a configure option was used then the macro is defined to <code>1</code>,
 * otherwise it is defined to 0.&nbsp;
 * This makes it possible for the compiler to warn you when you made a typo in the name of a macro.
 *
 * <b>Example:</b>
 *
 * \code
 * // Use '#if' not '#ifdef'.
 * #if CWDEBUG_ALLOC
 * Dout(dc::malloc, malloc_report << '.');
 * #endif
 * \endcode
 */

/** \defgroup enable_alloc --enable-alloc (CWDEBUG_ALLOC)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Turns on debugging for memory (de-)allocation.&nbsp;
 * This will warn you when you free an invalid block.&nbsp;
 * It also enables memory leak detection.
 *
 * \par When to use it
 *
 * In general, this should be used as long as you are developing a program, unless you want to do speed tests.
 *
 * \par Configure option
 *
 * This is enabled by default.&nbsp;
 * Use \shellcommand configure --disable-alloc \endshellcommand to disable it.
 *
 * \sa \ref book_allocations
 */

#define CWDEBUG_ALLOC @CW_CONFIG_ALLOC@

/** \defgroup enable_magic --enable-magic (CWDEBUG_MAGIC)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Adds a magic number to the beginning and the end of each
 * allocated memory block, and checks this when the block is
 * deleted or reallocated.
 *
 * \par When to use it
 *
 * In general, this should be used as long as you are developing a program, unless you want to do speed tests.
 *
 * \par Configure option
 *
 * This is enabled by default (but \ref enable_alloc must be enabled as well).&nbsp;
 * Use \shellcommand configure --disable-magic \endshellcommand to disable it.
 *
 * \sa \ref chapter_magic_numbers
 */

#define CWDEBUG_MAGIC (CWDEBUG_ALLOC && @CW_CONFIG_MAGIC@)

/** \defgroup enable_glibcxx_debug --enable-glibcxx_debug (CWDEBUG_GLIBCXX_DEBUG)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Compile libcwd itself with -D_GLIBCXX_DEBUG.
 * See "The libstdc++ debug mode" on http://gcc.gnu.org/onlinedocs/libstdc++/debug.html.
 *
 * Note that this flag changes the sizes and behavior of standard class templates such
 * as std::vector, and therefore you can only link code compiled with debug mode and
 * code compiled without debug mode if no instantiation of a container is passed
 * between the two translation units. Because this is always the case between your
 * custom debug.cc and libcwd, and most likely in many other cases-- libcwd enforces
 * that every compilation unit that includes libcwd/debug.h uses the same mode.
 *
 * \par When to use it
 *
 * It is a good idea to use this if you suspect problems related to iterators.
 * The disadvantage is that you need to compile your applications also with
 * -D_GLIBCXX_DEBUG and that this debug mode comes with a speed penality.
 *
 * \par Configure option
 *
 * This is disabled by default.
 * Use \shellcommand configure --enable-glibcxx_debug \endshellcommand to enable it.
 */

#define CWDEBUG_GLIBCXX_DEBUG @CW_CONFIG_GLIBCXX_DEBUG@

/** \defgroup enable_location --enable-location (CWDEBUG_LOCATION)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Adds code that supports source-file:line-number lookup.&nbsp;
 * This will load debugging symbols at the start of a program allowing
 * one to print source file / line number information.<BR><BR>
 * Turning this on causes libcwd to print source file and line
 * number information about where memory was allocated in the
 * memory allocation overview.&nbsp;
 * It also provides an interface, allowing applications that link
 * with libcwd to print debugging information using the symbol table.
 *
 * \par When to use it
 *
 * As a developer, especially when you are debugging memory allocations.
 *
 * \par Configure option
 *
 * This is enabled by default.&nbsp;
 * Use \shellcommand configure --disable-location \endshellcommand to disable it.
 *
 * \sa \ref chapter_alloc_locations
 */

#define CWDEBUG_LOCATION @CW_CONFIG_LOCATION@

/** \defgroup enable_libbfd --enable-libbfd (CWDEBUG_LIBBFD)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * This will cause libcwd to use GNU libbfd to load debug symbols and line number information.&nbsp;
 * If you don't have an ELF32 system then you might need this.&nbsp;
 * You will need libbfd.a and libiberty.a, which are part of GNU binutils.
 *
 * \sa \ref gpl_and_qpl
 *
 * \par When to use it
 *
 * Libcwd supports natively ELF32, stabs and DWARF-2 at the moment.&nbsp;
 * If you have an operating system that is non-ELF32, or that uses natively COFF,
 * then you might want to use this.&nbsp;  Otherwise there is no need to use libbfd.
 *
 * \par Configure option
 *
 * This is disabled by default.&nbsp;
 * You can enable it by specifying \shellcommand --enable-libbfd \endshellcommand during configuration.&nbsp;
 * Of course you'll need a working libbfd installed in that case.
 *
 * \sa \ref chapter_alloc_locations
 */
/** \page gpl_and_qpl Using GPL-ed code together with QPL-ed code.
 *
 * If you use GNU's libbfd then you are not allowed to distribute the resulting
 * executables because the GPL of libbfd prohibbits distribution of code that is not GPL-ed
 * and the resulting executable will be partly QPL-ed (this is a restriction of
 * the GPL not the QPL).&nbsp;
 * Note that if you have an ELF system (like linux) then you <EM>don't</EM> need libbfd.
 *
 * Note that if you want to release \em your program under the GNU GPL, and still link
 * with libcwd (and distribute the resulting binaries) then you can easily do that.&nbsp;
 * You can resolve the legal conflict for your program by adding a notice like this
 * to it: 
 *
 * <PRE>
 *     As a special exception, you have permission to link this program
 *     with the libcwd library and distribute executables, as long as you
 *     follow the requirements of the GNU GPL in regard to all of the
 *     software in the executable aside from libcwd.</PRE>
 *
 * You can do this, legally, if you are the copyright holder for the program.&nbsp;
 * Add it in the source files, after the notice that says the program is covered
 * by the GNU GPL.  [ Source: http://www.gnu.org/philosophy/license-list.html
 * section "The Qt Public License (QPL)." ].
 */

#define CWDEBUG_LIBBFD (CWDEBUG_LOCATION && @CW_CONFIG_LIBBFD@)

/** \defgroup enable_debug --enable-debug (CWDEBUG_DEBUG)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Turns on internal consistency checks of libcwd.&nbsp;
 * The use of these checks can slow down libcwd and are mainly intended for the maintainer of libcwd.
 *
 * \par When to use it
 *
 * When you think you found a bug in libcwd.
 *
 * \par Configure option
 *
 * This is disabled by default.&nbsp;
 * Use \shellcommand configure --enable-debug \endshellcommand to enable it.
 */

#define CWDEBUG_DEBUG @CW_CONFIG_DEBUG@

/** \defgroup enable_debug_output --enable-debug-output (CWDEBUG_DEBUGOUTPUT)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * When \ref enable_debug is enabled, this turns on a lot of extra debugging
 * output concerning the internal state of libcwd, and when \ref enable_alloc
 * is enabled, about internal allocations of libcwd.&nbsp;
 * This will not be usefull to you unless you manage to let the program
 * coredump even before it reaches main().
 *
 * \par When to use it
 *
 * Never, unless you are a developer of libcwd.
 *
 * \par Configure option
 *
 * This is disabled by default.&nbsp;
 * Use \shellcommand configure --enable-debug-output \endshellcommand to enable it.
 */

#define CWDEBUG_DEBUGOUTPUT (CWDEBUG_DEBUG && @CW_CONFIG_DEBUGOUTPUT@)

/** \defgroup enable_debugm --enable-debugm (CWDEBUG_DEBUGM)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Turns on even more debug output: Internal memory allocations are written to cerr.&nbsp;
 * This is needed for debugging the internal memory allocations of libcwd.
 *
 * \par When to use it
 *
 * Never, unless you are a developer of libcwd.
 *
 * \par Configure option
 *
 * This is disabled by default.&nbsp;
 * Use \shellcommand configure --enable-debug --enable-debugm \endshellcommand to enable it.
 */

#define CWDEBUG_DEBUGM (CWDEBUG_ALLOC && CWDEBUG_DEBUG && @CW_CONFIG_DEBUGM@)

/** \defgroup enable_marker --enable-marker (CWDEBUG_MARKER)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Includes support for markers.
 *
 * \par When to use it
 *
 * Always.
 *
 * \par Configure option
 *
 * This is enabled by default.&nbsp;
 * Use \shellcommand configure --disable-marker \endshellcommand to disable it.
 */

#define CWDEBUG_MARKER (CWDEBUG_ALLOC && @CW_CONFIG_MARKER@)

//
// autoconf defines that are needed.
//

#@CW_CONFIG_HAVE_PTHREADS@ LIBCWD_HAVE_PTHREAD

#if CWDEBUG_ALLOC
#@CW_CONFIG_HAVE___LIBC_MALLOC@ LIBCWD_HAVE___LIBC_MALLOC
#@CW_CONFIG_HAVE__LIBC_MALLOC@ LIBCWD_HAVE__LIBC_MALLOC
#@CW_CONFIG_HAVE_DLOPEN@ LIBCWD_HAVE_DLOPEN
#@CW_CONFIG_HAVE_POSIX_MEMALIGN@ LIBCWD_HAVE_POSIX_MEMALIGN
#@CW_CONFIG_HAVE_MEMALIGN@ LIBCWD_HAVE_MEMALIGN
#@CW_CONFIG_HAVE_VALLOC@ LIBCWD_HAVE_VALLOC
#if defined(LIBCWD_HAVE___LIBC_MALLOC) || defined(LIBCWD_HAVE__LIBC_MALLOC) || defined(LIBCWD_HAVE_DLOPEN)
#define LIBCWD_USE_EXTERNAL_C_LINKAGE_FOR_MALLOC
#endif
#endif

#if LIBCWD_THREAD_SAFE

#define LIBCWD_DO_MAX 8                         // Maximal total number of debug objects in a single application.
                                                // This costs about 640 kb of memory per object! (640 bytes * PTHREAD_THREADS_MAX).
#define LIBCWD_DC_MAX 256                       // Maximal total number of debug channels in a single application.
						// Costs 4 kb of memory per channel (exclusive the actual channels).

/** \defgroup enable_debugt --enable-debugt (CWDEBUG_DEBUGT)
 * \ingroup group_configuration
 *
 * \par Description
 *
 * Turns on sanity checks related to libcwds critical areas and cancellation points.&nbsp;
 * The checks test if cancellation has been explicitely deferred or disabled at the entrance
 * of a critical area and that no cancellation point is called from within critical areas
 * without cleanup handler.
 *
 * \par When to use it
 *
 * Never, unless you are a developer of libcwd.
 * If someone requests it then I might extend this to a user interface however.
 *
 * \par Configure option
 *
 * This is disabled by default.&nbsp;
 * Use \shellcommand configure --enable-debugt \endshellcommand to enable it.
 */

#define CWDEBUG_DEBUGT @CW_CONFIG_DEBUGT@
#else // !LIBCWD_THREAD_SAFE
#define LIBCWD_THREAD_SAFE 0
#define CWDEBUG_DEBUGT 0
#endif // !LIBCWD_THREAD_SAFE

//
// Configuration signature
//

#ifdef __cplusplus
namespace libcwd {

static unsigned long const config_signature_header_c =
	(
#if CWDEBUG_ALLOC
	1|
#endif
#if CWDEBUG_MAGIC
	2|
#endif
#if CWDEBUG_LOCATION
	4|
#endif
#if CWDEBUG_LIBBFD
	8|
#endif
#if CWDEBUG_DEBUG
	16|
#endif
#if CWDEBUG_DEBUGM
	32|
#endif
#if CWDEBUG_DEBUGT
	64|
#endif
#if CWDEBUG_MARKER
	128|
#endif
#if CWDEBUG_DEBUGOUTPUT
	256|
#endif
	(512 * (@VERSION_MAJOR@ + 128 * (@VERSION_MINOR@ + 128 * @VERSION_REVISION@))));

extern unsigned long get_config_signature_lib_c(void) __attribute__((const));
extern void conf_check_failed(void);
extern void version_check_failed(void);

/**
 * \ingroup chapter_special
 *
 * \brief Check if the linked library belongs to the header files being used.
 *
 * In order to be sure that the libcwd header files that are being used
 * belong to the libcwd.so shared object that the application linked with,
 * add the following line to the beginning of <CODE>main()</CODE>:
 *
 * \code
 * Debug( check_configuration() );
 * \endcode
 */
inline
void
check_configuration(void) {
  if (get_config_signature_lib_c() != config_signature_header_c)
  {
    if (get_config_signature_lib_c() / 512 != config_signature_header_c / 512)
      version_check_failed();
    else
      conf_check_failed();
  }
}

} // namespace libcwd
#endif // __cplusplus

#endif // LIBCWD_CONFIG_H
