/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
    qc_option.qpp

    Qore Programming Language

    Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.

    Note that the Qore library is released under a choice of three open-source
    licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
    information.
*/

#include <qore/Qore.h>

#include <openssl/evp.h>

#include <atomic>

#define QORE_CONST_HAVE_ATOMIC_MACROS std::atomic_int{}.is_lock_free()

#ifdef HAVE_CHECK_STACK_POS
#define QORE_CONST_HAVE_CHECK_STACK_POS 1
#else
#define QORE_CONST_HAVE_CHECK_STACK_POS 0
#endif

#ifdef HAVE_SIGNAL_HANDLING
#define QORE_CONST_HAVE_SIGNAL_HANDLING 1
#else
#define QORE_CONST_HAVE_SIGNAL_HANDLING 0
#endif

#ifdef DEBUG
#define QORE_CONST_DEBUG 1
#else
#define QORE_CONST_DEBUG 0
#endif

#ifdef HAVE_ROUND
#define QORE_CONST_HAVE_ROUND 1
#else
#define QORE_CONST_HAVE_ROUND 0
#endif

#ifdef HAVE_SETEUID
#define QORE_CONST_HAVE_SETEUID 1
#else
#define QORE_CONST_HAVE_SETEUID 0
#endif

#ifdef HAVE_SETEGID
#define QORE_CONST_HAVE_SETEGID 1
#else
#define QORE_CONST_HAVE_SETEGID 0
#endif

#ifdef HAVE_SYSTEM
#define QORE_CONST_HAVE_SYSTEM 1
#else
#define QORE_CONST_HAVE_SYSTEM 0
#endif

#ifdef HAVE_KILL
#define QORE_CONST_HAVE_KILL 1
#else
#define QORE_CONST_HAVE_KILL 0
#endif

#ifdef HAVE_FORK
#define QORE_CONST_HAVE_FORK 1
#else
#define QORE_CONST_HAVE_FORK 0
#endif

#ifdef HAVE_GETPPID
#define QORE_CONST_HAVE_GETPPID 1
#else
#define QORE_CONST_HAVE_GETPPID 0
#endif

#ifdef Q_HAVE_STATVFS
#define QORE_CONST_Q_HAVE_STATVFS 1
#else
#define QORE_CONST_Q_HAVE_STATVFS 0
#endif

#ifdef HAVE_SETSID
#define QORE_CONST_HAVE_SETSID 1
#else
#define QORE_CONST_HAVE_SETSID 0
#endif

#ifdef HAVE_PWD_H
#define QORE_CONST_HAVE_PWD_H 1
#else
#define QORE_CONST_HAVE_PWD_H 0
#endif

#ifdef HAVE_TERMIOS_H
#define QORE_CONST_HAVE_TERMIOS_H 1
#else
#define QORE_CONST_HAVE_TERMIOS_H 0
#endif

#ifdef HAVE_GETUID
#define QORE_CONST_HAVE_GETUID 1
#else
#define QORE_CONST_HAVE_GETUID 0
#endif

#ifdef HAVE_CHOWN
#define QORE_CONST_HAVE_CHOWN 1
#else
#define QORE_CONST_HAVE_CHOWN 0
#endif

#ifdef HAVE_STRUCT_FLOCK
#define QORE_CONST_HAVE_STRUCT_FLOCK 1
#else
#define QORE_CONST_HAVE_STRUCT_FLOCK 0
#endif

#ifdef HAVE_OPENSSL_SHA
#define QORE_CONST_HAVE_SHA 1
#else
#define QORE_CONST_HAVE_SHA 0
#endif

#if !defined(OPENSSL_NO_SHA256) && defined(HAVE_OPENSSL_SHA512)
#define QORE_CONST_HAVE_SHA256 1
#else
#define QORE_CONST_HAVE_SHA256 0
#endif

#if !defined(OPENSSL_NO_SHA512) && defined(HAVE_OPENSSL_SHA512)
#define QORE_CONST_HAVE_SHA512 1
#else
#define QORE_CONST_HAVE_SHA512 0
#endif

#ifdef OPENSSL_HAVE_MDC2
#define QORE_CONST_HAVE_MDC2 1
#else
#define QORE_CONST_HAVE_MDC2 0
#endif

#ifndef OPENSSL_NO_MD2
#define QORE_CONST_HAVE_MD2 1
#else
#define QORE_CONST_HAVE_MD2 0
#endif

#ifndef OPENSSL_NO_RC5
#define QORE_CONST_HAVE_RC5 1
#else
#define QORE_CONST_HAVE_RC5 0
#endif

#ifndef HAVE_OPENSSL_INIT_CRYPTO
#define QORE_CONST_HAVE_DSS 1
#else
#define QORE_CONST_HAVE_DSS 0
#endif

#ifdef HAVE_SYMLINK
#define QORE_CONST_HAVE_SYMLINK 1
#else
#define QORE_CONST_HAVE_SYMLINK 0
#endif

#if defined(HAVE_UNISTD_H) && defined(_SC_OPEN_MAX)
#define QORE_CONST_HAVE_CLOSE_ALL_FD 1
#else
#define QORE_CONST_HAVE_CLOSE_ALL_FD 0
#endif

#ifdef HAVE_GETIFADDRS
#define QORE_CONST_HAVE_GET_NETIF_LIST 1
#else
#define QORE_CONST_HAVE_GET_NETIF_LIST 0
#endif

#ifdef QORE_MANAGE_STACK
#define QORE_CONST_HAVE_MANAGE_STACK 1
#else
#define QORE_CONST_HAVE_MANAGE_STACK 0
#endif

#ifdef QORE_HAVE_GET_STACK_SIZE
#define QORE_CONST_HAVE_GET_STACK_SIZE 1
#else
#define QORE_CONST_HAVE_GET_STACK_SIZE 0
#endif

#ifdef QORE_HAVE_THREAD_NAME
#define QORE_CONST_HAVE_THREAD_NAME 1
#else
#define QORE_CONST_HAVE_THREAD_NAME 0
#endif

/** @defgroup option_constants Option Constants
    Option constants
*/
///@{
namespace Qore::Option;
//! Indicates if the %Qore library supports fast atomic reference counting
/** Note that if this constant is @ref False, atomic operations are supported by mutexes and are therefore slower than with native atomic reference counting operations
 */
const HAVE_ATOMIC_OPERATIONS = bool(QORE_CONST_HAVE_ATOMIC_MACROS);

//! Indicates if protection against stack overruns is provided
const HAVE_STACK_GUARD = bool(QORE_CONST_HAVE_CHECK_STACK_POS);

//! Indicates if UNIX-style signal handling is available
/** If this constant is @ref False, then the set_signal_handler() and remove_signal_handler() functions are not available.

    @note This constant is always @ref False on native Windows ports and is also @ref False if the qore library was initialized with signals disabled (such as with <tt>qore -b</tt> or <tt>qore --disable-signals</tt>)

    @see @ref signal_handling
 */
const HAVE_SIGNAL_HANDLING = qore((bool)(QORE_CONST_HAVE_SIGNAL_HANDLING && !(qore_library_options & QLO_DISABLE_SIGNAL_HANDLING)));

//! Indicates if the %Qore library has been built with debugging enabled
const HAVE_LIBRARY_DEBUGGING = bool(QORE_CONST_DEBUG);

//! Indicates if active thread stack tracing has been enabled as a debugging option and if the get_alT_thread_call_stacks() function is available
/** @since %Qore 0.9 always @ref True
*/
const HAVE_RUNTIME_THREAD_STACK_TRACE = bool(true);

//! Indicates if the round() function is available; the availability of this function depends on the presence of the C-library's %round() function
const HAVE_ROUND = bool(QORE_CONST_HAVE_ROUND);

//! Indicates if the seteuid() function is available; the availabilty of this function depends on the system's underlying C-library
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_SETEUID = bool(QORE_CONST_HAVE_SETEUID);

//! Indicates if the setegid() function is available; the availabilty of this function depends on the system's underlying C-library
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_SETEGID = bool(QORE_CONST_HAVE_SETEGID);

//! Indicates if the system() function is available
const HAVE_SYSTEM = bool(QORE_CONST_HAVE_SYSTEM);

//! Indicates if the kill() function is available
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_KILL = bool(QORE_CONST_HAVE_KILL);

//! Indicates if the fork() function is available
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_FORK = bool(QORE_CONST_HAVE_FORK);

//! Indicates if the getppid() function is available
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_GETPPID = bool(QORE_CONST_HAVE_GETPPID);

//! Indicates if the statvfs() function is available
const HAVE_STATVFS = bool(QORE_CONST_Q_HAVE_STATVFS);

//! Indicates if the setsid() function is available
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_SETSID = bool(QORE_CONST_HAVE_SETSID);

//! Indicates if the %Qore library supports the is_executable() function
/** @note Currently this function is only available when running on UNIX or UNIX-like platforms
 */
const HAVE_IS_EXECUTABLE = bool(QORE_CONST_HAVE_PWD_H);

//! Indicates if the symlink() function is available
/** @note This constant is always @ref False on native Windows ports

    @since %Qore 0.8.6 although the symlink() function was added in 0.8.5
 */
const HAVE_SYMLINK = bool(QORE_CONST_HAVE_SYMLINK);

//! Indicates if the TermIOS class is available
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_TERMIOS = bool(QORE_CONST_HAVE_TERMIOS_H);

//! Indicates if UNIX-style user management functionality is available (ex: getuid(), setuid(), getgid(), setgid(), etc)
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_UNIX_USERMGT = bool(QORE_CONST_HAVE_GETUID);

//! Indicates if UNIX-style file management functionality is available (ex: chown(), Dir::chgrp(), etc)
/** @note This constant is always @ref False on native Windows ports
 */
const HAVE_UNIX_FILEMGT = bool(QORE_CONST_HAVE_CHOWN);

//! Indicates if the %Qore library supports file locking; currently this depends on UNIX-style file locking with the fnctl() function
/** @note Currently this function is only available when running on UNIX or UNIX-like platforms
 */
const HAVE_FILE_LOCKING = bool(QORE_CONST_HAVE_STRUCT_FLOCK);

//! Indicates if the %Qore library supports deterministic garbage collection for managing circular references between objects
const HAVE_DETERMINISTIC_GC = bool(1);

//! Indicates if the openssl library used to build the qore library supported the SHA0 algorithm and therefore if the SHA() and SHA_bin() functions are available
const HAVE_SHA = bool(QORE_CONST_HAVE_SHA);

//! Indicates if the openssl library used to build the qore library supported the SHA224 algorithm and therefore if the SHA224() and SHA224_bin() functions are available
const HAVE_SHA224 = bool(QORE_CONST_HAVE_SHA256);

//! Indicates if the openssl library used to build the qore library supported the SHA256 algorithm and therefore if the SHA256() and SHA256_bin() functions are available
const HAVE_SHA256 = bool(QORE_CONST_HAVE_SHA256);

//! Indicates if the openssl library used to build the qore library supported the SHA384 algorithm and therefore if the SHA384() and SHA384_bin() functions are available
const HAVE_SHA384 = bool(QORE_CONST_HAVE_SHA512);

//! Indicates if the openssl library used to build the qore library supported the SHA512 algorithm and therefore if the SHA512() and SHA512_bin() functions are available
const HAVE_SHA512 = bool(QORE_CONST_HAVE_SHA512);

//! Indicates if the openssl library used to build the qore library supported the MDC2 algorithm and therefore if the MDC2() and MDC2_bin() functions are available
const HAVE_MDC2 = bool(QORE_CONST_HAVE_MDC2);

//! Indicates if the openssl library used to build the qore library supported the MD2 algorithm and therefore if the MD2() and MD2_bin() functions are available
const HAVE_MD2 = bool(QORE_CONST_HAVE_MD2);

//! Indicates if the openssl library used to build the qore library supported the RC5 encryption algorithm and therefore if the rc5_encrypt_cbc(), rc5_decrypt_cbc() and rc5_decrypt_cbc_to_string() functions are available
const HAVE_RC5 = bool(QORE_CONST_HAVE_RC5);

//! Indicates if the openssl library used to build the qore library supported the outdated DSS and DSS1 digest algorithms and therefore if the DSS(), DSS1(), DSS_bin(), and DSS1_bin() functions are available
const HAVE_DSS = bool(QORE_CONST_HAVE_DSS);

//! Indicates if the close_all_fd() function is available
const HAVE_CLOSE_ALL_FD = bool(QORE_CONST_HAVE_CLOSE_ALL_FD);

//! Indicates if the get_netif_list() function is available
/** @since %Qore 0.9.0
*/
const HAVE_GET_NETIF_LIST = bool(QORE_CONST_HAVE_GET_NETIF_LIST);

//! Indicates if the get_default_thread_stack_size() and set_default_thread_stack_size() functions are available
/** @since %Qore 0.9.0
*/
const HAVE_MANAGE_STACK = bool(QORE_CONST_HAVE_MANAGE_STACK);

//! Indicates if the get_stack_size() function is available
/** @since %Qore 0.9.0
*/
const HAVE_GET_STACK_SIZE = bool(QORE_CONST_HAVE_GET_STACK_SIZE);

//! Indicates if the get_thread_name() and set_thread_name() functions are available
/** @since %Qore 0.9.0
*/
const HAVE_THREAD_NAME = bool(QORE_CONST_HAVE_THREAD_NAME);
///@}
