/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJ_CONFIG_H__
#define __PJ_CONFIG_H__


/**
 * @file config.h
 * @brief PJLIB Main configuration settings.
 */

/********************************************************************
 * Include compiler specific configuration.
 */
#if defined(_MSC_VER)
#  include <pj/compat/cc_msvc.h>
#elif defined(__clang__)
#  include <pj/compat/cc_clang.h>
#elif defined(__GNUC__)
#  include <pj/compat/cc_gcc.h>
#elif defined(__CW32__)
#  include <pj/compat/cc_mwcc.h>
#elif defined(__MWERKS__)
#  include <pj/compat/cc_codew.h>
#elif defined(__GCCE__)
#  include <pj/compat/cc_gcce.h>
#elif defined(__ARMCC__)
#  include <pj/compat/cc_armcc.h>
#else
#  error "Unknown compiler."
#endif

/* PJ_ALIGN_DATA is compiler specific directive to align data address */
#ifndef PJ_ALIGN_DATA
#  error "PJ_ALIGN_DATA is not defined!"
#endif

/********************************************************************
 * Include target OS specific configuration.
 */
#if defined(PJ_AUTOCONF)
    /*
     * Autoconf
     */
#   include <pj/compat/os_auto.h>

#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
    /*
     * SymbianOS
     */
#  include <pj/compat/os_symbian.h>

#elif defined(PJ_WIN32_WINCE) || defined(_WIN32_WCE) || defined(UNDER_CE)
    /*
     * Windows CE
     */
#   undef PJ_WIN32_WINCE
#   define PJ_WIN32_WINCE   1
#   include <pj/compat/os_win32_wince.h>

    /* Also define Win32 */
#   define PJ_WIN32 1

#elif defined(PJ_WIN32_WINPHONE8) || defined(_WIN32_WINPHONE8)
    /*
     * Windows Phone 8
     */
#   undef PJ_WIN32_WINPHONE8
#   define PJ_WIN32_WINPHONE8   1
#   include <pj/compat/os_winphone8.h>

    /* Also define Win32 */
#   define PJ_WIN32 1

#elif defined(PJ_WIN32_UWP) || defined(_WIN32_UWP)
    /*
     * Windows UWP
     */
#   undef PJ_WIN32_UWP
#   define PJ_WIN32_UWP   1
#   include <pj/compat/os_winuwp.h>

    /* Define Windows phone */
#   define PJ_WIN32_WINPHONE8 1

    /* Also define Win32 */
#   define PJ_WIN32 1

#elif defined(PJ_WIN32) || defined(_WIN32) || defined(__WIN32__) || \
        defined(WIN32) || defined(PJ_WIN64) || defined(_WIN64) || \
        defined(WIN64) || defined(__TOS_WIN__) 
#   if defined(PJ_WIN64) || defined(_WIN64) || defined(WIN64)
        /*
         * Win64
         */
#       undef PJ_WIN64
#       define PJ_WIN64 1
#   endif
#   undef PJ_WIN32
#   define PJ_WIN32 1
#   include <pj/compat/os_win32.h>

#elif defined(PJ_LINUX) || defined(linux) || defined(__linux)
    /*
     * Linux
     */
#   undef PJ_LINUX
#   define PJ_LINUX         1
#   include <pj/compat/os_linux.h>

#elif defined(PJ_PALMOS) && PJ_PALMOS!=0
    /*
     * Palm
     */
#  include <pj/compat/os_palmos.h>

#elif defined(PJ_SUNOS) || defined(sun) || defined(__sun)
    /*
     * SunOS
     */
#   undef PJ_SUNOS
#   define PJ_SUNOS         1
#   include <pj/compat/os_sunos.h>

#elif defined(PJ_DARWINOS) || defined(__MACOSX__) || \
      defined (__APPLE__) || defined (__MACH__)
    /*
     * MacOS X
     */
#   undef PJ_DARWINOS
#   define PJ_DARWINOS      1
#   include <pj/compat/os_darwinos.h>

#elif defined(PJ_RTEMS) && PJ_RTEMS!=0
    /*
     * RTEMS
     */
#  include <pj/compat/os_rtems.h>
#else
#   error "Please specify target os."
#endif


/********************************************************************
 * Target machine specific configuration.
 */
#if defined(PJ_AUTOCONF)
    /*
     * Autoconf configured
     */
#include <pj/compat/m_auto.h>

#elif defined (PJ_M_I386) || defined(_i386_) || defined(i_386_) || \
        defined(_X86_) || defined(x86) || defined(__i386__) || \
        defined(__i386) || defined(_M_IX86) || defined(__I86__)
    /*
     * Generic i386 processor family, little-endian
     */
#   undef PJ_M_I386
#   define PJ_M_I386            1
#   define PJ_M_NAME            "i386"
#   define PJ_HAS_PENTIUM       1
#   define PJ_IS_LITTLE_ENDIAN  1
#   define PJ_IS_BIG_ENDIAN     0

#elif defined (PJ_M_X86_64) || defined(__amd64__) || defined(__amd64) || \
        defined(__x86_64__) || defined(__x86_64) || \
        defined(_M_X64) || defined(_M_AMD64)
    /*
     * AMD 64bit processor, little endian
     */
#   undef PJ_M_X86_64
#   define PJ_M_X86_64          1
#   define PJ_M_NAME            "x86_64"
#   define PJ_HAS_PENTIUM       1
#   define PJ_IS_LITTLE_ENDIAN  1
#   define PJ_IS_BIG_ENDIAN     0

#elif defined(PJ_M_IA64) || defined(__ia64__) || defined(_IA64) || \
        defined(__IA64__) || defined(   _M_IA64)
    /*
     * Intel IA64 processor, default to little endian
     */
#   undef PJ_M_IA64
#   define PJ_M_IA64            1
#   define PJ_M_NAME            "ia64"
#   define PJ_HAS_PENTIUM       1
#   define PJ_IS_LITTLE_ENDIAN  1
#   define PJ_IS_BIG_ENDIAN     0

#elif defined (PJ_M_M68K) && PJ_M_M68K != 0

    /*
     * Motorola m68k processor, big endian
     */
#   undef PJ_M_M68K
#   define PJ_M_M68K            1
#   define PJ_M_NAME            "m68k"
#   define PJ_HAS_PENTIUM       0
#   define PJ_IS_LITTLE_ENDIAN  0
#   define PJ_IS_BIG_ENDIAN     1


#elif defined (PJ_M_ALPHA) || defined (__alpha__) || defined (__alpha) || \
        defined (_M_ALPHA)
    /*
     * DEC Alpha processor, little endian
     */
#   undef PJ_M_ALPHA
#   define PJ_M_ALPHA           1
#   define PJ_M_NAME            "alpha"
#   define PJ_HAS_PENTIUM       0
#   define PJ_IS_LITTLE_ENDIAN  1
#   define PJ_IS_BIG_ENDIAN     0


#elif defined(PJ_M_MIPS) || defined(__mips__) || defined(__mips) || \
        defined(__MIPS__) || defined(MIPS) || defined(_MIPS_)
    /*
     * MIPS, bi-endian, so raise error if endianness is not configured
     */
#   undef PJ_M_MIPS
#   define PJ_M_MIPS            1
#   define PJ_M_NAME            "mips"
#   define PJ_HAS_PENTIUM       0
#   if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
#       error Endianness must be declared for this processor
#   endif


#elif defined (PJ_M_SPARC) || defined(  __sparc__) || defined(__sparc)
    /*
     * Sun Sparc, big endian
     */
#   undef PJ_M_SPARC
#   define PJ_M_SPARC           1
#   define PJ_M_NAME            "sparc"
#   define PJ_HAS_PENTIUM       0
#   define PJ_IS_LITTLE_ENDIAN  0
#   define PJ_IS_BIG_ENDIAN     1

#elif defined(ARM) || defined(_ARM_) ||  defined(__arm__) || \
       defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__)
#   define PJ_HAS_PENTIUM       0
    /*
     * ARM, bi-endian, so raise error if endianness is not configured
     */
#   if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
#       error Endianness must be declared for this processor
#   endif
#   if defined (PJ_M_ARMV7) || defined(ARMV7)
#       undef PJ_M_ARMV7
#       define PJ_M_ARM7                1
#       define PJ_M_NAME                "armv7"
#   elif defined (PJ_M_ARMV4) || defined(ARMV4)
#       undef PJ_M_ARMV4
#       define PJ_M_ARMV4               1
#       define PJ_M_NAME                "armv4"
#   elif defined (PJ_M_ARM64) || defined(ARM64) || defined(__aarch64__)
#       undef PJ_M_ARM64
#       define PJ_M_ARM64               1
#       define PJ_M_NAME                "arm64"
#   endif 

#elif defined (PJ_M_POWERPC) || defined(__powerpc) || defined(__powerpc__) || \
        defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || \
        defined(_ARCH_PPC)
    /*
     * PowerPC, bi-endian, so raise error if endianness is not configured
     */
#   undef PJ_M_POWERPC
#   define PJ_M_POWERPC         1
#   define PJ_M_NAME            "powerpc"
#   define PJ_HAS_PENTIUM       0
#   if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
#       error Endianness must be declared for this processor
#   endif

#elif defined (PJ_M_NIOS2) || defined(__nios2) || defined(__nios2__) || \
      defined(__NIOS2__) || defined(__M_NIOS2) || defined(_ARCH_NIOS2)
    /*
     * Nios2, little endian
     */
#   undef PJ_M_NIOS2
#   define PJ_M_NIOS2           1
#   define PJ_M_NAME            "nios2"
#   define PJ_HAS_PENTIUM       0
#   define PJ_IS_LITTLE_ENDIAN  1
#   define PJ_IS_BIG_ENDIAN     0
                
#else
#   error "Please specify target machine."
#endif

/* Include size_t definition. */
#include <pj/compat/size_t.h>

/* Include site/user specific configuration to control PJLIB features.
 * YOU MUST CREATE THIS FILE YOURSELF!!
 */
#include <pj/config_site.h>

/********************************************************************
 * PJLIB Features.
 */

/* Overrides for DOXYGEN */
#ifdef DOXYGEN
#   undef PJ_FUNCTIONS_ARE_INLINED
#   undef PJ_HAS_FLOATING_POINT
#   undef PJ_LOG_MAX_LEVEL
#   undef PJ_LOG_MAX_SIZE
#   undef PJ_LOG_USE_STACK_BUFFER
#   undef PJ_TERM_HAS_COLOR
#   undef PJ_POOL_DEBUG
#   undef PJ_HAS_TCP
#   undef PJ_MAX_HOSTNAME
#   undef PJ_IOQUEUE_MAX_HANDLES
#   undef FD_SETSIZE
#   undef PJ_HAS_SEMAPHORE
#   undef PJ_HAS_EVENT_OBJ
#   undef PJ_EXCEPTION_USE_WIN32_SEH
#   undef PJ_HAS_ERROR_STRING

#   define PJ_HAS_IPV6  1
#endif

/**
 * @defgroup pj_config Build Configuration
 * @{
 *
 * This section contains macros that can set during PJLIB build process
 * to controll various aspects of the library.
 *
 * <b>Note</b>: the values in this page does NOT necessarily reflect to the
 * macro values during the build process.
 */

/**
 * If this macro is set to 1, it will enable some debugging checking
 * in the library.
 *
 * Default: equal to (NOT NDEBUG).
 */
#ifndef PJ_DEBUG
#  ifndef NDEBUG
#    define PJ_DEBUG                1
#  else
#    define PJ_DEBUG                0
#  endif
#endif

/**
 * Enable this macro to activate logging to mutex/semaphore related events.
 * This is useful to troubleshoot concurrency problems such as deadlocks.
 * In addition, you should also add PJ_LOG_HAS_THREAD_ID flag to the
 * log decoration to assist the troubleshooting.
 *
 * Default: 0
 */
#ifndef PJ_DEBUG_MUTEX
#   define PJ_DEBUG_MUTEX           0
#endif

/**
 * Expand functions in *_i.h header files as inline.
 *
 * Default: 0.
 */
#ifndef PJ_FUNCTIONS_ARE_INLINED
#  define PJ_FUNCTIONS_ARE_INLINED  0
#endif

/**
 * Use floating point computations in the library.
 *
 * Default: 1.
 */
#ifndef PJ_HAS_FLOATING_POINT
#  define PJ_HAS_FLOATING_POINT     1
#endif

/**
 * Declare maximum logging level/verbosity. Lower number indicates higher
 * importance, with the highest importance has level zero. The least
 * important level is five in this implementation, but this can be extended
 * by supplying the appropriate implementation.
 *
 * The level conventions:
 *  - 0: fatal error
 *  - 1: error
 *  - 2: warning
 *  - 3: info
 *  - 4: debug
 *  - 5: trace
 *  - 6: more detailed trace
 *
 * Default: 4
 */
#ifndef PJ_LOG_MAX_LEVEL
#  define PJ_LOG_MAX_LEVEL   5
#endif

/**
 * Maximum message size that can be sent to output device for each call
 * to PJ_LOG(). If the message size is longer than this value, it will be cut.
 * This may affect the stack usage, depending whether PJ_LOG_USE_STACK_BUFFER
 * flag is set.
 *
 * Default: 4000
 */
#ifndef PJ_LOG_MAX_SIZE
#  define PJ_LOG_MAX_SIZE           4000
#endif

/**
 * Log buffer.
 * Does the log get the buffer from the stack? (default is yes).
 * If the value is set to NO, then the buffer will be taken from static
 * buffer, which in this case will make the log function non-reentrant.
 *
 * Default: 1
 */
#ifndef PJ_LOG_USE_STACK_BUFFER
#  define PJ_LOG_USE_STACK_BUFFER   1
#endif

/**
 * Enable log indentation feature.
 *
 * Default: 1
 */
#ifndef PJ_LOG_ENABLE_INDENT
#   define PJ_LOG_ENABLE_INDENT        1
#endif

/**
 * Number of PJ_LOG_INDENT_CHAR to put every time pj_log_push_indent()
 * is called.
 *
 * Default: 1
 */
#ifndef PJ_LOG_INDENT_SIZE
#   define PJ_LOG_INDENT_SIZE        1
#endif

/**
 * Log indentation character.
 *
 * Default: space
 */
#ifndef PJ_LOG_INDENT_CHAR
#   define PJ_LOG_INDENT_CHAR       '.'
#endif

/**
 * Log sender width.
 *
 * Default: 22 (for 64-bit machines), 14 otherwise
 */
#ifndef PJ_LOG_SENDER_WIDTH
#   if PJ_HAS_STDINT_H
#       include <stdint.h>
#       if (UINTPTR_MAX == 0xffffffffffffffff)
#           define PJ_LOG_SENDER_WIDTH  22
#       else
#           define PJ_LOG_SENDER_WIDTH  14
#       endif
#   else
#       define PJ_LOG_SENDER_WIDTH  14
#   endif
#endif

/**
 * Log thread name width.
 *
 * Default: 12
 */
#ifndef PJ_LOG_THREAD_WIDTH
#   define PJ_LOG_THREAD_WIDTH      12
#endif

/**
 * Colorfull terminal (for logging etc).
 *
 * Default: 1
 */
#ifndef PJ_TERM_HAS_COLOR
#  define PJ_TERM_HAS_COLOR         1
#endif


/**
 * Set this flag to non-zero to enable various checking for pool
 * operations. When this flag is set, assertion must be enabled
 * in the application.
 *
 * This will slow down pool creation and destruction and will add
 * few bytes of overhead, so application would normally want to 
 * disable this feature on release build.
 *
 * Default: 0
 */
#ifndef PJ_SAFE_POOL
#   define PJ_SAFE_POOL             0
#endif


/**
 * If pool debugging is used, then each memory allocation from the pool
 * will call malloc(), and pool will release all memory chunks when it
 * is destroyed. This works better when memory verification programs
 * such as Rational Purify is used.
 *
 * Default: 0
 */
#ifndef PJ_POOL_DEBUG
#  define PJ_POOL_DEBUG             0
#endif


/**
 * If enabled, when calling pj_pool_release(), the memory pool content
 * will be wiped out first before released.
 *
 * Default: 0
 */
#ifndef PJ_POOL_RELEASE_WIPE_DATA
#  define PJ_POOL_RELEASE_WIPE_DATA     0
#endif


/**
 * If enabled, when allocating memory, pool will only search for a maximum
 * number of blocks specified before deciding that the pool is full and
 * a new memory block needs to be created.
 *
 * Set it to 0 to disable the limitation (i.e. it will search all blocks).
 *
 * Default: 5
 */
#ifndef PJ_POOL_MAX_SEARCH_BLOCK_COUNT
#   define PJ_POOL_MAX_SEARCH_BLOCK_COUNT 5
#endif


/**
 * Enable timer debugging facility. When this is enabled, application
 * can call pj_timer_heap_dump() to show the contents of the timer
 * along with the source location where the timer entries were scheduled.
 * See https://github.com/pjsip/pjproject/issues/1527 for more info.
 *
 * Default: 1
 */
#ifndef PJ_TIMER_DEBUG
#  define PJ_TIMER_DEBUG            1
#endif


/**
 * If enabled, the timer will keep internal copies of the timer entries.
 * This will increase the robustness and stability of the timer (against
 * accidental modification or premature deallocation of the timer entries) and
 * makes it easier to troubleshoot any timer related issues, with the overhead
 * of additional memory space required.
 *
 * Note that the detection against premature deallocation only works if the
 * freed memory content has changed (such as if it's been reallocated and
 * overwritten by another data. Alternatively, you can enable
 * PJ_POOL_RELEASE_WIPE_DATA which will erase the data first before releasing
 * the memory).
 *
 * Default: 1 (enabled)
 */
#ifndef PJ_TIMER_USE_COPY
#  define PJ_TIMER_USE_COPY    1
#endif


/**
 * If enabled, the timer use sorted linked list instead of binary heap tree
 * structure. Note that using sorted linked list is intended for debugging
 * purposes and will hamper performance significantly when scheduling large
 * number of entries.
 *
 * Default: 0 (Use binary heap tree)
 */
#ifndef PJ_TIMER_USE_LINKED_LIST
#  define PJ_TIMER_USE_LINKED_LIST    0
#endif

/**
 * Set this to 1 to enable debugging on the group lock. Default: 0
 */
#ifndef PJ_GRP_LOCK_DEBUG
#  define PJ_GRP_LOCK_DEBUG     0
#endif


/**
 * Specify this as \a stack_size argument in #pj_thread_create() to specify
 * that thread should use default stack size for the current platform.
 *
 * Default: 8192
 */
#ifndef PJ_THREAD_DEFAULT_STACK_SIZE 
#  define PJ_THREAD_DEFAULT_STACK_SIZE    8192
#endif


/**
 * Specify if PJ_CHECK_STACK() macro is enabled to check the sanity of 
 * the stack. The OS implementation may check that no stack overflow 
 * occurs, and it also may collect statistic about stack usage. Note
 * that this will increase the footprint of the libraries since it
 * tracks the filename and line number of each functions.
 */
#ifndef PJ_OS_HAS_CHECK_STACK
#       define PJ_OS_HAS_CHECK_STACK            0
#endif

/**
 * Do we have alternate pool implementation?
 *
 * Default: 0
 */
#ifndef PJ_HAS_POOL_ALT_API
#   define PJ_HAS_POOL_ALT_API      PJ_POOL_DEBUG
#endif


/**
 * Support TCP in the library.
 * Disabling TCP will reduce the footprint slightly (about 6KB).
 *
 * Default: 1
 */
#ifndef PJ_HAS_TCP
#  define PJ_HAS_TCP                1
#endif

/**
 * Support IPv6 in the library. If this support is disabled, some IPv6 
 * related functions will return PJ_EIPV6NOTSUP.
 *
 * Default: 0 (disabled, for now)
 */
#ifndef PJ_HAS_IPV6
#  define PJ_HAS_IPV6               0
#endif

 /**
 * Maximum hostname length.
 * Libraries sometimes needs to make copy of an address to stack buffer;
 * the value here affects the stack usage.
 *
 * Note that the length here should include the NULL termination. In other
 * words, the maximum hostname length is PJ_MAX_HOSTNAME with the NULL
 * termination and PJ_MAX_HOSTNAME-1 without the NULL termination.
 *
 * Default: 254
 */
#ifndef PJ_MAX_HOSTNAME
#  define PJ_MAX_HOSTNAME           (254)
#endif

/**
 * Maximum consecutive identical error for accept() operation before
 * activesock stops calling the next ioqueue accept.
 *
 * Default: 50
 */
#ifndef PJ_ACTIVESOCK_MAX_CONSECUTIVE_ACCEPT_ERROR
#   define PJ_ACTIVESOCK_MAX_CONSECUTIVE_ACCEPT_ERROR 50
#endif


/*
 * I/O queue implementation backends.
 * Select one of these implementations in PJ_IOQUEUE_IMP.
 */

/** No/dummy I/O queue */
#define PJ_IOQUEUE_IMP_NONE         0

/** Using select() */
#define PJ_IOQUEUE_IMP_SELECT       1

/** Using epoll() (experimental) */
#define PJ_IOQUEUE_IMP_EPOLL        2

/** Using Windows I/O Completion Ports (experimental) */
#define PJ_IOQUEUE_IMP_IOCP         3

/** Using MacOS/BSD kqueue (experimental) */
#define PJ_IOQUEUE_IMP_KQUEUE       4

/** Using Windows UWP socket (deprecated) */
#define PJ_IOQUEUE_IMP_UWP          5

/** Using Symbian (deprecated) */
#define PJ_IOQUEUE_IMP_SYMBIAN      6

/**
 * I/O queue implementation backend.
 *
 * Default: PJ_IOQUEUE_IMP_SELECT
 */
#ifndef PJ_IOQUEUE_IMP
#   define PJ_IOQUEUE_IMP               PJ_IOQUEUE_IMP_SELECT
#endif


/**
 * Constants for declaring the maximum handles that can be supported by
 * a single IOQ framework. This constant might not be relevant to the 
 * underlying I/O queue impelementation, but still, developers should be 
 * aware of this constant, to make sure that the program will not break when
 * the underlying implementation changes.
 */
#ifndef PJ_IOQUEUE_MAX_HANDLES
#   define PJ_IOQUEUE_MAX_HANDLES       (64)
#endif


/**
 * If PJ_IOQUEUE_HAS_SAFE_UNREG macro is defined, then ioqueue will do more
 * things to ensure thread safety of handle unregistration operation by
 * employing reference counter to each handle.
 *
 * In addition, the ioqueue will preallocate memory for the handles, 
 * according to the maximum number of handles that is specified during 
 * ioqueue creation.
 *
 * All applications would normally want this enabled, but you may disable
 * this if:
 *  - there is no dynamic unregistration to all ioqueues.
 *  - there is no threading, or there is no preemptive multitasking.
 *
 * Default: 1
 */
#ifndef PJ_IOQUEUE_HAS_SAFE_UNREG
#   define PJ_IOQUEUE_HAS_SAFE_UNREG    1
#endif


/**
 * Default concurrency setting for sockets/handles registered to ioqueue.
 * This controls whether the ioqueue is allowed to call the key's callback
 * concurrently/in parallel. The default is yes, which means that if there
 * are more than one pending operations complete simultaneously, more
 * than one threads may call the key's callback at the same time. This
 * generally would promote good scalability for application, at the 
 * expense of more complexity to manage the concurrent accesses.
 *
 * Please see the ioqueue documentation for more info.
 */
#ifndef PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY
#   define PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY   1
#endif


/* Sanity check:
 *  if ioqueue concurrency is disallowed, PJ_IOQUEUE_HAS_SAFE_UNREG
 *  must be enabled.
 */
#if (PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY==0) && (PJ_IOQUEUE_HAS_SAFE_UNREG==0)
#   error PJ_IOQUEUE_HAS_SAFE_UNREG must be enabled if ioqueue concurrency \
          is disabled
#endif


/**
 * When safe unregistration (PJ_IOQUEUE_HAS_SAFE_UNREG) is configured in
 * ioqueue, the PJ_IOQUEUE_KEY_FREE_DELAY macro specifies how long the
 * ioqueue key is kept in closing state before it can be reused.
 *
 * The value is in miliseconds.
 *
 * Default: 500 msec.
 */
#ifndef PJ_IOQUEUE_KEY_FREE_DELAY
#   define PJ_IOQUEUE_KEY_FREE_DELAY    500
#endif


/**
 * Default flags for epoll_flags member of  pj_ioqueue_cfg structure.
 * The values are combination of pj_ioqueue_epoll_flag constants.
 *
 * Default: PJ_IOQUEUE_EPOLL_AUTO
 */
#ifndef PJ_IOQUEUE_DEFAULT_EPOLL_FLAGS
#   define PJ_IOQUEUE_DEFAULT_EPOLL_FLAGS PJ_IOQUEUE_EPOLL_AUTO
#endif


/**
 * This setting ensures that the read callback is invoked without holding
 * the key mutex, even when concurrency is disabled.
 *
 * Note: This may introduce a race condition between key unregistration
 * and the read callback. Therefore, the application must be prepared
 * to handle a read callback even after pj_ioqueue_unregister() has returned.
 *
 * Default: 0 (disabled).
 */
#ifndef PJ_IOQUEUE_CALLBACK_NO_LOCK
#   define PJ_IOQUEUE_CALLBACK_NO_LOCK  0
#endif


/**
 * Determine if FD_SETSIZE is changeable/set-able. If so, then we will
 * set it to PJ_IOQUEUE_MAX_HANDLES. Currently we detect this by checking
 * for Winsock.
 */
#ifndef PJ_FD_SETSIZE_SETABLE
#   if (defined(PJ_HAS_WINSOCK_H) && PJ_HAS_WINSOCK_H!=0) || \
       (defined(PJ_HAS_WINSOCK2_H) && PJ_HAS_WINSOCK2_H!=0)
#       define PJ_FD_SETSIZE_SETABLE    1
#   else
#       define PJ_FD_SETSIZE_SETABLE    0
#   endif
#endif

/**
 * Overrides FD_SETSIZE so it is consistent throughout the library.
 * We only do this if we detected that FD_SETSIZE is changeable. If
 * FD_SETSIZE is not set-able, then PJ_IOQUEUE_MAX_HANDLES must be
 * set to value lower than FD_SETSIZE.
 */
#if PJ_FD_SETSIZE_SETABLE
    /* Only override FD_SETSIZE if the value has not been set */
#   ifndef FD_SETSIZE
#       define FD_SETSIZE               PJ_IOQUEUE_MAX_HANDLES
#   endif
#else
    /* When FD_SETSIZE is not changeable, check if PJ_IOQUEUE_MAX_HANDLES
     * is lower than FD_SETSIZE value.
     *
     * Update: Not all ioqueue backends require this (such as epoll), so
     * this check will be done on the ioqueue implementation itself, such as
     * ioqueue select.
     */
/*
#   ifdef FD_SETSIZE
#       if PJ_IOQUEUE_MAX_HANDLES > FD_SETSIZE
#           error "PJ_IOQUEUE_MAX_HANDLES is greater than FD_SETSIZE"
#       endif
#   endif
*/
#endif


/**
 * Specify whether #pj_enum_ip_interface() function should exclude
 * loopback interfaces.
 *
 * Default: 1
 */
#ifndef PJ_IP_HELPER_IGNORE_LOOPBACK_IF
#   define PJ_IP_HELPER_IGNORE_LOOPBACK_IF      1
#endif


/**
 * Has semaphore functionality?
 *
 * Default: 1
 */
#ifndef PJ_HAS_SEMAPHORE
#  define PJ_HAS_SEMAPHORE          1
#endif

/**
 * Use dispatch semaphores on Darwin.
 *
 * Default: 1 on Darwin, 0 otherwise
 */
#ifndef PJ_SEMAPHORE_USE_DISPATCH_SEM
#   if defined(PJ_DARWINOS) && PJ_DARWINOS != 0
#       define PJ_SEMAPHORE_USE_DISPATCH_SEM    1
#   else
#       define PJ_SEMAPHORE_USE_DISPATCH_SEM    0
#   endif
#endif


/**
 * Event object (for synchronization, e.g. in Win32)
 *
 * Default: 1
 */
#ifndef PJ_HAS_EVENT_OBJ
#  define PJ_HAS_EVENT_OBJ          1
#endif


/**
 * Maximum file name length.
 */
#ifndef PJ_MAXPATH
#   define PJ_MAXPATH               260
#endif


/**
 * Enable name registration for exceptions with #pj_exception_id_alloc().
 * If this feature is enabled, then the library will keep track of
 * names associated with each exception ID requested by application via
 * #pj_exception_id_alloc().
 *
 * Disabling this macro will reduce the code and .bss size by a tad bit.
 * See also #PJ_MAX_EXCEPTION_ID.
 *
 * Default: 1
 */
#ifndef PJ_HAS_EXCEPTION_NAMES
#   define PJ_HAS_EXCEPTION_NAMES   1
#endif

/**
 * Maximum number of unique exception IDs that can be requested
 * with #pj_exception_id_alloc(). For each entry, a small record will
 * be allocated in the .bss segment.
 *
 * Default: 16
 */
#ifndef PJ_MAX_EXCEPTION_ID
#   define PJ_MAX_EXCEPTION_ID      16
#endif

/**
 * Should we use Windows Structured Exception Handling (SEH) for the
 * PJLIB exceptions.
 *
 * Default: 0
 */
#ifndef PJ_EXCEPTION_USE_WIN32_SEH
#  define PJ_EXCEPTION_USE_WIN32_SEH 0
#endif

/**
 * Should we attempt to use Pentium's rdtsc for high resolution
 * timestamp.
 *
 * Default: 0
 */
#ifndef PJ_TIMESTAMP_USE_RDTSC
#   define PJ_TIMESTAMP_USE_RDTSC   0
#endif

/**
 * Is native platform error positive number?
 * Default: 1 (yes)
 */
#ifndef PJ_NATIVE_ERR_POSITIVE
#   define PJ_NATIVE_ERR_POSITIVE   1
#endif
 
/**
 * Include error message string in the library (pj_strerror()).
 * This is very much desirable!
 *
 * Default: 1
 */
#ifndef PJ_HAS_ERROR_STRING
#   define PJ_HAS_ERROR_STRING      1
#endif


/**
 * Include pj_stricmp_alnum() and pj_strnicmp_alnum(), i.e. custom
 * functions to compare alnum strings. On some systems, they're faster
 * then stricmp/strcasecmp, but they can be slower on other systems.
 * When disabled, pjlib will fallback to stricmp/strnicmp.
 * 
 * Default: 0
 */
#ifndef PJ_HAS_STRICMP_ALNUM
#   define PJ_HAS_STRICMP_ALNUM     0
#endif

/**
 * Prohibit the use of unsafe string functions such as strcpy(), strncpy(),
 * strcat(), and vsprintf().
 */
#ifndef PJ_BAN_UNSAFE_STR_FUNCS
#   define PJ_BAN_UNSAFE_STR_FUNCS  0
#endif

/**
 * Prohibit the use of strcpy() and pj_ansi_strcpy(), use pj_ansi_strxcpy()
 * instead.
 */
#ifndef PJ_BAN_STRCPY
#   define PJ_BAN_STRCPY            PJ_BAN_UNSAFE_STR_FUNCS
#endif

/**
 * Prohibit the use of strncpy() and pj_ansi_strncpy(), use pj_ansi_strxcpy()
 * instead.
 */
#ifndef PJ_BAN_STRNCPY
#   define PJ_BAN_STRNCPY           PJ_BAN_UNSAFE_STR_FUNCS
#endif

/**
 * Prohibit the use of strcat() and pj_ansi_strcat(), use pj_ansi_strxcat()
 * instead.
 */
#ifndef PJ_BAN_STRCAT
#   define PJ_BAN_STRCAT            PJ_BAN_UNSAFE_STR_FUNCS
#endif

/**
 * Prohibit the use of sprintf() and pj_ansi_sprintf(),
 * use pj_ansi_snprintf() instead.
 */
#ifndef PJ_BAN_SPRINTF
#   define PJ_BAN_SPRINTF           PJ_BAN_UNSAFE_STR_FUNCS
#endif

/**
 * Prohibit the use of vsprintf() and pj_ansi_vsprintf(),
 * use pj_ansi_vsnprintf() instead.
 */
#ifndef PJ_BAN_VSPRINTF
#   define PJ_BAN_VSPRINTF          PJ_BAN_UNSAFE_STR_FUNCS
#endif

/*
 * Warn about obsolete macros.
 *
 * PJ_ENABLE_EXTRA_CHECK has been deprecated in 2.13.
 */
#if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK==0
#   ifdef _MSC_VER
#       pragma message("Warning: PJ_ENABLE_EXTRA_CHECK macro is deprecated"\
                       " and has no effect")
#   else
#       warning "PJ_ENABLE_EXTRA_CHECK macro is deprecated and has no effect"
#   endif
#endif


/*
 * Types of QoS backend implementation.
 */

/** 
 * Dummy QoS backend implementation, will always return error on all
 * the APIs.
 */
#define PJ_QOS_DUMMY        1

/** QoS backend based on setsockopt(IP_TOS) */
#define PJ_QOS_BSD          2

/** QoS backend for Windows Mobile 6 */
#define PJ_QOS_WM           3

/** QoS backend for Symbian */
#define PJ_QOS_SYMBIAN      4

/** QoS backend for Darwin */
#define PJ_QOS_DARWIN       5

/**
 * Force the use of some QoS backend API for some platforms.
 */
#ifndef PJ_QOS_IMPLEMENTATION
#   if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE && _WIN32_WCE >= 0x502
        /* Windows Mobile 6 or later */
#       define PJ_QOS_IMPLEMENTATION    PJ_QOS_WM
#   elif defined(PJ_DARWINOS)
        /* Darwin OS (e.g: iOS, MacOS, tvOS) */
#       define PJ_QOS_IMPLEMENTATION    PJ_QOS_DARWIN
#   endif
#endif


/**
 * Enable secure socket. For most platforms, this is implemented using
 * OpenSSL or GnuTLS, so this will require one of those libraries to
 * be installed. For Symbian platform, this is implemented natively
 * using CSecureSocket.
 *
 * Default: 0 (for now)
 */
#ifndef PJ_HAS_SSL_SOCK
#  define PJ_HAS_SSL_SOCK           0
#endif


/*
 * Secure socket implementation.
 * Select one of these implementations in PJ_SSL_SOCK_IMP.
 */
/** Disable SSL socket */
#define PJ_SSL_SOCK_IMP_NONE        0

/** Using OpenSSL */
#define PJ_SSL_SOCK_IMP_OPENSSL     1

/** Using GnuTLS */
#define PJ_SSL_SOCK_IMP_GNUTLS      2

/** Using Apple's Secure Transport (deprecated in MacOS 10.15 & iOS 13.0) */
#define PJ_SSL_SOCK_IMP_DARWIN      3

/** Using Apple's Network framework */
#define PJ_SSL_SOCK_IMP_APPLE       4

/** Using Windows's Schannel */
#define PJ_SSL_SOCK_IMP_SCHANNEL    5

/** Using Mbed TLS */
#define PJ_SSL_SOCK_IMP_MBEDTLS     6

/**
 * Select which SSL socket implementation to use. Currently pjlib supports
 * PJ_SSL_SOCK_IMP_OPENSSL, which uses OpenSSL, and PJ_SSL_SOCK_IMP_GNUTLS,
 * which uses GnuTLS. Setting this to PJ_SSL_SOCK_IMP_NONE will disable
 * secure socket.
 *
 * Default is PJ_SSL_SOCK_IMP_NONE if PJ_HAS_SSL_SOCK is not set, otherwise
 * it is PJ_SSL_SOCK_IMP_OPENSSL.
 */
#ifndef PJ_SSL_SOCK_IMP
#   if PJ_HAS_SSL_SOCK==0
#       define PJ_SSL_SOCK_IMP              PJ_SSL_SOCK_IMP_NONE
#   else
#       define PJ_SSL_SOCK_IMP              PJ_SSL_SOCK_IMP_OPENSSL
#   endif
#endif


/**
 * Define the maximum number of ciphers supported by the secure socket.
 *
 * Default: 256
 */
#ifndef PJ_SSL_SOCK_MAX_CIPHERS
#  define PJ_SSL_SOCK_MAX_CIPHERS   256
#endif


/**
 * Specify what should be set as the available list of SSL_CIPHERs. For
 * example, set this as "DEFAULT" to use the default cipher list (Note:
 * PJSIP release 2.4 and before used this "DEFAULT" setting).
 *
 * Default: "HIGH:-COMPLEMENTOFDEFAULT"
 */
#ifndef PJ_SSL_SOCK_OSSL_CIPHERS
#  define PJ_SSL_SOCK_OSSL_CIPHERS   "HIGH:-COMPLEMENTOFDEFAULT"
#endif


/**
 * Define the maximum number of curves supported by the secure socket.
 *
 * Default: 32
 */
#ifndef PJ_SSL_SOCK_MAX_CURVES
#  define PJ_SSL_SOCK_MAX_CURVES   32
#endif

/**
 * Use OpenSSL thread locking callback. This is only applicable for OpenSSL
 * version prior to 1.1.0
 *
 * Default: 1 (enabled)
 */
#ifndef PJ_SSL_SOCK_OSSL_USE_THREAD_CB
#   define PJ_SSL_SOCK_OSSL_USE_THREAD_CB   1
#else
#   define PJ_SSL_SOCK_OSSL_USE_THREAD_CB   0
#endif


/**
 * Disable WSAECONNRESET error for UDP sockets on Win32 platforms. See
 * https://github.com/pjsip/pjproject/issues/1197.
 *
 * Default: 1
 */
#ifndef PJ_SOCK_DISABLE_WSAECONNRESET
#   define PJ_SOCK_DISABLE_WSAECONNRESET    1
#endif


/**
 * Maximum number of socket options in pj_sockopt_params.
 *
 * Default: 4
 */
#ifndef PJ_MAX_SOCKOPT_PARAMS
#   define PJ_MAX_SOCKOPT_PARAMS            4
#endif


/* Specify if JNI_OnLoad() will be defined in the library. If enabled,
 * PJSIP will set the Java Virtual Machine (JVM) inside JNI_OnLoad().
 *
 * Since there can only be one JNI_OnLoad() in a library loaded from Java,
 * you can disable this if the implementation is already defined somewhere
 * else. Then you can set the JVM using the API pj_jni_set_jvm() instead.
 *
 * Default: enabled for Android
 */
#ifndef PJ_JNI_HAS_JNI_ONLOAD
#  define PJ_JNI_HAS_JNI_ONLOAD             PJ_ANDROID
#endif

/**
 * pj_atomic_slist implementation.
 * Select one of these implementations in PJ_ATOMIC_SLIST_IMPLEMENTATION.
 */
 /** Using os independent "cross-platform" implementation */
#define PJ_ATOMIC_SLIST_GENERIC             0

 /** Using Windows's single linked list */
#define PJ_ATOMIC_SLIST_WIN32               1

/**
 * Select which pj_atomic_slist implementation to use. Currently pjlib supports
 * PJ_ATOMIC_SLIST_GENERIC, which uses internal pjsip os independent 
 * "cross-platform" implementation, and 
 * PJ_ATOMIC_SLIST_WIN32, which uses Windows's single linked list.
 * The last option is very fast, but is supported on Windows platform only.
 *
 * Default is PJ_ATOMIC_SLIST_WIN32 on Windows platform, 
 *            otherwise PJ_ATOMIC_SLIST_GENERIC.
 */
#ifndef PJ_ATOMIC_SLIST_IMPLEMENTATION
#   ifdef PJ_WIN32
#       define PJ_ATOMIC_SLIST_IMPLEMENTATION   PJ_ATOMIC_SLIST_WIN32
#   else
#       define PJ_ATOMIC_SLIST_IMPLEMENTATION   PJ_ATOMIC_SLIST_GENERIC
#   endif // PJ_WIN32
#endif  //PJ_ATOMIC_SLIST_IMPLEMENTATION

/**
 * File I/O backend implementation.
 * Select one of these implementations in PJ_FILE_IO.
 * By default, PJ_FILE_IO_WIN32 is selected on Windows platform,
 * otherwise PJ_FILE_IO_ANSI is selected.
 * 
 * select ioqueue supports both backend under Windows, but IOCP
 * supports Win32 file I/O only.
 */
#define PJ_FILE_IO_WIN32 0  /* Using Win32 file I/O  */
#define PJ_FILE_IO_ANSI 1   /* Using ANSI C file I/O */

#ifndef PJ_FILE_IO
#   ifdef PJ_WIN32
#       define PJ_FILE_IO   PJ_FILE_IO_WIN32
#   else
#       define PJ_FILE_IO   PJ_FILE_IO_ANSI
#   endif // PJ_WIN32
#elif PJ_FILE_IO == PJ_FILE_IO_ANSI && PJ_IOQUEUE_IMP == PJ_IOQUEUE_IMP_IOCP
#   error IOCP ioqueue does not support ANSI file backend
#endif  //PJ_FILE_IO

/** @} */

/********************************************************************
 * General macros.
 */

/**
 * @defgroup pj_dll_target Building Dynamic Link Libraries (DLL/DSO)
 * @ingroup pj_config
 * @{
 *
 * The libraries support generation of dynamic link libraries for
 * Symbian ABIv2 target (.dso/Dynamic Shared Object files, in Symbian
 * terms). Similar procedures may be applied for Win32 DLL with some 
 * modification.
 *
 * Depending on the platforms, these steps may be necessary in order to
 * produce the dynamic libraries:
 *  - Create the (Visual Studio) projects to produce DLL output. PJLIB
 *    does not provide ready to use project files to produce DLL, so
 *    you need to create these projects yourself. For Symbian, the MMP
 *    files have been setup to produce DSO files for targets that 
 *    require them.
 *  - In the (Visual Studio) projects, some macros need to be declared
 *    so that appropriate modifiers are added to symbol declarations
 *    and definitions. Please see the macro section below for information
 *    regarding these macros. For Symbian, these have been taken care by the
 *    MMP files.
 *  - Some build systems require .DEF file to be specified when creating
 *    the DLL. For Symbian, .DEF files are included in pjlib distribution,
 *    in <tt>pjlib/build.symbian</tt> directory. These DEF files are 
 *    created by running <tt>./makedef.sh all</tt> from this directory,
 *    inside Mingw.
 *
 * Macros related for building DLL/DSO files:
 *  - For platforms that supports dynamic link libraries generation,
 *    it must declare <tt>PJ_EXPORT_SPECIFIER</tt> macro which value contains
 *    the prefix to be added to symbol definition, to export this 
 *    symbol in the DLL/DSO. For example, on Win32/Visual Studio, the
 *    value of this macro is \a __declspec(dllexport), and for ARM 
 *    ABIv2/Symbian, the value is \a EXPORT_C. 
 *  - For platforms that supports linking with dynamic link libraries,
 *    it must declare <tt>PJ_IMPORT_SPECIFIER</tt> macro which value contains
 *    the prefix to be added to symbol declaration, to import this 
 *    symbol from a DLL/DSO. For example, on Win32/Visual Studio, the
 *    value of this macro is \a __declspec(dllimport), and for ARM 
 *    ABIv2/Symbian, the value is \a IMPORT_C. 
 *  - Both <tt>PJ_EXPORT_SPECIFIER</tt> and <tt>PJ_IMPORT_SPECIFIER</tt> 
 *    macros above can be declared in your \a config_site.h if they are not
 *    declared by pjlib.
 *  - When PJLIB is built as DLL/DSO, both <tt>PJ_DLL</tt> and 
 *    <tt>PJ_EXPORTING</tt> macros must be declared, so that 
 *     <tt>PJ_EXPORT_SPECIFIER</tt> modifier will be added into function
 *    definition.
 *  - When application wants to link dynamically with PJLIB, then it
 *    must declare <tt>PJ_DLL</tt> macro when using/including PJLIB header,
 *    so that <tt>PJ_IMPORT_SPECIFIER</tt> modifier is properly added into 
 *    symbol declarations.
 *
 * When <b>PJ_DLL</b> macro is not declared, static linking is assumed.
 *
 * For example, here are some settings to produce DLLs with Visual Studio
 * on Windows/Win32:
 *  - Create Visual Studio projects to produce DLL. Add the appropriate 
 *    project dependencies to avoid link errors.
 *  - In the projects, declare <tt>PJ_DLL</tt> and <tt>PJ_EXPORTING</tt> 
 *    macros.
 *  - Declare these macros in your <tt>config_site.h</tt>:
 \verbatim
        #define PJ_EXPORT_SPECIFIER  __declspec(dllexport)
        #define PJ_IMPORT_SPECIFIER  __declspec(dllimport)
 \endverbatim
 *  - And in the application (that links with the DLL) project, add 
 *    <tt>PJ_DLL</tt> in the macro declarations.
 */

/** @} */

/**
 * @defgroup pj_config Build Configuration
 * @{
 */

/**
 * @def PJ_INLINE(type)
 * @param type The return type of the function.
 * Expand the function as inline.
 */
#define PJ_INLINE(type)   PJ_INLINE_SPECIFIER type

/**
 * This macro declares platform/compiler specific specifier prefix
 * to be added to symbol declaration to export the symbol when PJLIB
 * is built as dynamic library.
 *
 * This macro should have been added by platform specific headers,
 * if the platform supports building dynamic library target. 
 */
#ifndef PJ_EXPORT_DECL_SPECIFIER
#   define PJ_EXPORT_DECL_SPECIFIER
#endif


/**
 * This macro declares platform/compiler specific specifier prefix
 * to be added to symbol definition to export the symbol when PJLIB
 * is built as dynamic library.
 *
 * This macro should have been added by platform specific headers,
 * if the platform supports building dynamic library target. 
 */
#ifndef PJ_EXPORT_DEF_SPECIFIER
#   define PJ_EXPORT_DEF_SPECIFIER
#endif


/**
 * This macro declares platform/compiler specific specifier prefix
 * to be added to symbol declaration to import the symbol.
 *
 * This macro should have been added by platform specific headers,
 * if the platform supports building dynamic library target.
 */
#ifndef PJ_IMPORT_DECL_SPECIFIER
#   define PJ_IMPORT_DECL_SPECIFIER
#endif


/**
 * This macro has been deprecated. It will evaluate to nothing.
 */
#ifndef PJ_EXPORT_SYMBOL
#   define PJ_EXPORT_SYMBOL(x)
#endif


/**
 * @def PJ_DECL(type)
 * @param type The return type of the function.
 * Declare a function.
 */
#if defined(PJ_DLL)
#   if defined(PJ_EXPORTING)
#       define PJ_DECL(type)        PJ_EXPORT_DECL_SPECIFIER type
#   else
#       define PJ_DECL(type)        PJ_IMPORT_DECL_SPECIFIER type
#   endif
#elif !defined(PJ_DECL)
#   if defined(__cplusplus)
#       define PJ_DECL(type)        type
#   else
#       define PJ_DECL(type)        extern type
#   endif
#endif


/**
 * @def PJ_DEF(type)
 * @param type The return type of the function.
 * Define a function.
 */
#if defined(PJ_DLL) && defined(PJ_EXPORTING)
#   define PJ_DEF(type)             PJ_EXPORT_DEF_SPECIFIER type
#elif !defined(PJ_DEF)
#   define PJ_DEF(type)             type
#endif


/**
 * @def PJ_DECL_NO_RETURN(type)
 * @param type The return type of the function.
 * Declare a function that will not return.
 */
/**
 * @def PJ_IDECL_NO_RETURN(type)
 * @param type The return type of the function.
 * Declare an inline function that will not return.
 */
/**
 * @def PJ_BEGIN_DECL
 * Mark beginning of declaration section in a header file.
 */
/**
 * @def PJ_END_DECL
 * Mark end of declaration section in a header file.
 */
#ifdef __cplusplus
#  define PJ_DECL_NO_RETURN(type)   PJ_DECL(type) PJ_NORETURN
#  define PJ_IDECL_NO_RETURN(type)  PJ_INLINE(type) PJ_NORETURN
#  define PJ_BEGIN_DECL             extern "C" {
#  define PJ_END_DECL               }
#else
#  define PJ_DECL_NO_RETURN(type)   PJ_NORETURN PJ_DECL(type)
#  define PJ_IDECL_NO_RETURN(type)  PJ_NORETURN PJ_INLINE(type)
#  define PJ_BEGIN_DECL
#  define PJ_END_DECL
#endif



/**
 * @def PJ_DECL_DATA(type)
 * @param type The data type.
 * Declare a global data.
 */ 
#if defined(PJ_DLL)
#   if defined(PJ_EXPORTING)
#       define PJ_DECL_DATA(type)   PJ_EXPORT_DECL_SPECIFIER extern type
#   else
#       define PJ_DECL_DATA(type)   PJ_IMPORT_DECL_SPECIFIER extern type
#   endif
#elif !defined(PJ_DECL_DATA)
#   define PJ_DECL_DATA(type)       extern type
#endif


/**
 * @def PJ_DEF_DATA(type)
 * @param type The data type.
 * Define a global data.
 */ 
#if defined(PJ_DLL) && defined(PJ_EXPORTING)
#   define PJ_DEF_DATA(type)        PJ_EXPORT_DEF_SPECIFIER type
#elif !defined(PJ_DEF_DATA)
#   define PJ_DEF_DATA(type)        type
#endif


/**
 * @def PJ_IDECL(type)
 * @param type  The function's return type.
 * Declare a function that may be expanded as inline.
 */
/**
 * @def PJ_IDEF(type)
 * @param type  The function's return type.
 * Define a function that may be expanded as inline.
 */

#if PJ_FUNCTIONS_ARE_INLINED
#  define PJ_IDECL(type)  PJ_INLINE(type)
#  define PJ_IDEF(type)   PJ_INLINE(type)
#else
#  define PJ_IDECL(type)  PJ_DECL(type)
#  define PJ_IDEF(type)   PJ_DEF(type)
#endif


/**
 * @def PJ_UNUSED_ARG(arg)
 * @param arg   The argument name.
 * PJ_UNUSED_ARG prevents warning about unused argument in a function.
 */
#define PJ_UNUSED_ARG(arg)  (void)arg

/**
 * @def PJ_TODO(id)
 * @param id    Any identifier that will be printed as TODO message.
 * PJ_TODO macro will display TODO message as warning during compilation.
 * Example: PJ_TODO(CLEAN_UP_ERROR);
 */
#ifndef PJ_TODO
#  define PJ_TODO(id)       TODO___##id:
#endif

/**
 * Simulate race condition by sleeping the thread in strategic locations.
 * Default: no!
 */
#ifndef PJ_RACE_ME
#  define PJ_RACE_ME(x)
#endif

/**
 * Function attributes to inform that the function may throw exception.
 *
 * @param x     The exception list, enclosed in parenthesis.
 */
#define __pj_throw__(x)

/** @} */

/********************************************************************
 * Sanity Checks
 */
#ifndef PJ_HAS_HIGH_RES_TIMER
#  error "PJ_HAS_HIGH_RES_TIMER is not defined!"
#endif

#if !defined(PJ_HAS_PENTIUM)
#  error "PJ_HAS_PENTIUM is not defined!"
#endif

#if !defined(PJ_IS_LITTLE_ENDIAN)
#  error "PJ_IS_LITTLE_ENDIAN is not defined!"
#endif

#if !defined(PJ_IS_BIG_ENDIAN)
#  error "PJ_IS_BIG_ENDIAN is not defined!"
#endif

#if !defined(PJ_EMULATE_RWMUTEX)
#  error "PJ_EMULATE_RWMUTEX should be defined in compat/os_xx.h"
#endif

#if !defined(PJ_THREAD_SET_STACK_SIZE)
#  error "PJ_THREAD_SET_STACK_SIZE should be defined in compat/os_xx.h"
#endif

#if !defined(PJ_THREAD_ALLOCATE_STACK)
#  error "PJ_THREAD_ALLOCATE_STACK should be defined in compat/os_xx.h"
#endif

PJ_BEGIN_DECL

/** PJLIB version major number. */
#define PJ_VERSION_NUM_MAJOR    2

/** PJLIB version minor number. */
#define PJ_VERSION_NUM_MINOR    16

/** PJLIB version revision number. */
#define PJ_VERSION_NUM_REV      0

/**
 * Extra suffix for the version (e.g. "-trunk"), or empty for
 * web release version.
 */
#define PJ_VERSION_NUM_EXTRA    ""

/**
 * PJLIB version number consists of three bytes with the following format:
 * 0xMMIIRR00, where MM: major number, II: minor number, RR: revision
 * number, 00: always zero for now.
 */
#define PJ_VERSION_NUM  ((PJ_VERSION_NUM_MAJOR << 24) | \
                         (PJ_VERSION_NUM_MINOR << 16) | \
                         (PJ_VERSION_NUM_REV << 8))

/**
 * PJLIB version string constant. @see pj_get_version()
 */
PJ_DECL_DATA(const char*) PJ_VERSION;

/**
 * Get PJLIB version string.
 *
 * @return #PJ_VERSION constant.
 */
PJ_DECL(const char*) pj_get_version(void);

/**
 * Dump configuration to log with verbosity equal to info(3).
 */
PJ_DECL(void) pj_dump_config(void);

PJ_END_DECL


#endif  /* __PJ_CONFIG_H__ */

