/*
 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef YARP_CONFIG_SYSTEM_H
#define YARP_CONFIG_SYSTEM_H

// System headers
/* #undef YARP_HAS_EXECINFO_H */
/* #undef YARP_HAS_SYS_WAIT_H */
#define YARP_HAS_SYS_TYPES_H
/* #undef YARP_HAS_SYS_PRCTL_H */
/* #undef YARP_HAS_CSIGNAL */
#define YARP_HAS_SIGNAL_H
/* #undef YARP_HAS_SYS_SIGNAL_H */
/* #undef YARP_HAS_NETDB_H */
/* #undef YARP_HAS_DLFCN_H */
/* #undef YARP_HAS_IFADDRS_H */

// Size of pointers
#define YARP_POINTER_SIZE 8


///@{

/**
 * \def YARP_COMPILER_MESSAGE
 *
 * Print a message at build time on supported compilers.
 *
 * For example:
 * \code{.c}
 * YARP_COMPILER_MESSAGE(This is a custom compiler message)
 * \endcode
 * will print "This is a custom compiler message".
 *
 * \param x Message.
 *
 * \see YARP_COMPILER_WARNING, YARP_COMPILER_ERROR, YARP_COMPILER_DEPRECATED_WARNING
 */

/**
 * \def YARP_COMPILER_WARNING
 *
 * Generate a warning at build time on supported compilers.
 *
 * For example:
 * \code{.c}
 * YARP_COMPILER_WARNING(This is a custom compiler warning)
 * \endcode
 * will generate a warning "This is a custom compiler warning"
 *
 * \param x Warning message.
 *
 * \see YARP_COMPILER_MESSAGE, YARP_COMPILER_ERROR, YARP_COMPILER_DEPRECATED_WARNING
 *
 */

/**
 * \def YARP_COMPILER_ERROR
 *
 * Generate an error at build time on supported compilers.
 *
 * For example:
 * \code{.c}
 * YARP_COMPILER_ERROR(This is a custom compiler error)
 * \endcode
 * will generate an error "This is a custom compiler error".
 *
 * \param x Error message.
 *
 * \see YARP_COMPILER_MESSAGE, YARP_COMPILER_WARNING, YARP_COMPILER_DEPRECATED_WARNING
 */

/**
 * \def YARP_COMPILER_DEPRECATED_WARNING
 *
 * Generate a warning at build time on supported compilers if deprecated
 * warnings are enabled.
 *
 * This can be useful for example to deprecate a header file.
 *
 * \param x Deprecation message.
 *
 * \see YARP_COMPILER_MESSAGE, YARP_COMPILER_WARNING, YARP_COMPILER_ERROR
 */

///@}


#if defined(_MSC_VER)
  // see https://yal.cc/emitting-custom-warnings-errors-in-visual-studio-custom-build-events/
  // and https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/yxkt8b26(v=vs.100)?redirectedfrom=MSDN
  #define __YARP_STR2(x) #x
  #define __YARP_STR1(x) __YARP_STR2(x)
  #define __YARP_LOC __FILE__ "(" __YARP_STR1(__LINE__) ")"
  #define YARP_COMPILER_MESSAGE(x) __pragma(message(__YARP_LOC ": message : " #x))
  #define YARP_COMPILER_WARNING(x) __pragma(message(__YARP_LOC " : warning:" #x))
  #define YARP_COMPILER_ERROR(x)   __pragma(message(__YARP_LOC " : error:" #x))

#elif defined(__GNUC__)
  // see https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
  #define __YARP_DO_PRAGMA(x) _Pragma (#x)
  #define YARP_COMPILER_MESSAGE(x) __YARP_DO_PRAGMA(message #x)
  #define YARP_COMPILER_WARNING(x) __YARP_DO_PRAGMA(GCC warning #x)
  #define YARP_COMPILER_ERROR(x)  __YARP_DO_PRAGMA(GCC error #x)
#else
  #define YARP_COMPILER_MESSAGE(x)
  #define YARP_COMPILER_WARNING(x)
  #define YARP_COMPILER_ERROR(x)
#endif

#ifndef YARP_NO_DEPRECATED_WARNINGS
  #define YARP_COMPILER_DEPRECATED_WARNING(x) YARP_COMPILER_WARNING(x)
#else
  #define YARP_COMPILER_DEPRECATED_WARNING(x)
#endif


///@{

/**
 * \def YARP_BEGIN_PACK
 *
 * Starts 1 byte packing for structs/classes.
 *
 * Instructs the compiler that the following structure/class has to be
 * packed with 1 byte boundary.  This is conditionally generated depending
 * on the compiler and architecture. It assures interoperability of network
 * communication between compilers.
 *
 * \see \ref port_expert_data, YARP_END_PACK
 */

/**
 * \def YARP_END_PACK
 *
 * Ends 1 byte packing for structs/classes.
 *
 * Instructs the compiler that the default packing can be reinstated.
 *
 * \see \ref port_expert_data YARP_BEGIN_PACK
 */

///@}


#if defined(CYGWIN)
#  define YARP_BEGIN_PACK \
     _Pragma("pack(1)")
#  define YARP_END_PACK \
     _Pragma("pack()")
#elif defined(_MSC_VER)
// use packing and make no apologies about it
#  define YARP_BEGIN_PACK \
     __pragma(warning(push)) \
     __pragma(warning(disable:4103)) \
     __pragma(pack(push, 1))
#  define YARP_END_PACK \
     __pragma(pack(pop)) \
     __pragma(warning(pop))
#elif defined(__linux__)
#  define YARP_BEGIN_PACK \
     _Pragma("pack(1)")
#  define YARP_END_PACK _Pragma("pack()")
#elif defined(__DARWIN__)
#  define YARP_BEGIN_PACK \
     _Pragma("pack(1)")
#  define YARP_END_PACK \
     _Pragma("pack()")
#elif defined(__APPLE__)
#  define YARP_BEGIN_PACK \
     _Pragma("pack(1)")
#  define YARP_END_PACK \
     _Pragma("pack()")
#elif defined(__QNX4__)
#  define YARP_BEGIN_PACK \
     _Pragma(" pack (push) ;") \
     _Pragma(" pack (1) ;")
#  define YARP_END_PACK \
     _Pragma(" pack (pop) ;")
#elif defined(__QNX6__)
//_Pragma("align 1")
#  define YARP_BEGIN_PACK \
     _Pragma("pack(1)")
//_Pragma("align 0")
#  define YARP_END_PACK \
     _Pragma("pack()")
#else
#  define YARP_BEGIN_PACK
#  define YARP_END_PACK
#endif


///@{

/**
 * \def YARP_WARNING_PUSH
 *
 * Starts a temporary alteration of the enabled warnings.
 *
 * \see YARP_WARNING_POP
 */

/**
 * \def YARP_WARNING_POP
 *
 * Ends a temporary alteration of the enabled warnings.
 *
 * \see YARP_WARNING_PUSH
 */

/**
 * \def YARP_DISABLE_DEPRECATED_WARNING
 *
 * Disable deprecated warnings in the following code.
 *
 * It should be used in this way:
 * \code
 *  YARP_WARNING_PUSH
 *  YARP_DISABLE_DEPRECATED_WARNING
 *   do_something_deprecated();
 *  YARP_WARNING_POP
 * \endcode
 *
 * \see YARP_WARNING_PUSH, YARP_WARNING_POP
 */

/**
 * \def YARP_DISABLE_DLL_INTERFACE_WARNING
 *
 * Disable MSVC C4251 warnings in the following code.
 *
 * It should be used in this way:
 * \code
 *  YARP_WARNING_PUSH
 *  YARP_DISABLE_DLL_INTERFACE_WARNING
 *   std::string foo;
 *   std::string bar;
 *  YARP_WARNING_POP
 * \endcode
 *
 * \see YARP_WARNING_PUSH, YARP_WARNING_POP,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS
 */

/**
 * \def YARP_SUPPRESS_DLL_INTERFACE_WARNING
 *
 * Suppress MSVC C4251 warning for the next line.
 * It should be used in this way:
 * \code
 *  YARP_SUPPRESS_DLL_INTERFACE_WARNING
 *  static const std::string foo;
 * \endcode
 *
 * \see YARP_DISABLE_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS
 */

/**
 * \def YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG
 *
 * Suppress MSVC C4251 warning for the declaration.
 * It should be used in this way:
 * \code
 *  YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG(std::string) foo;
 * \endcode
 *
 * \warning As a side effect this macro suppresses the warning also for the
 *          following line.
 *
 * \see YARP_DISABLE_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS
 */

/**
 * \def YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS
 *
 * Suppress MSVC C4251 warning for the declaration.
 * It should be used in this way:
 * \code
 *  YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS(std::map<int, int>) foo;
 * \endcode
 *
 * \warning As a side effect this macro suppresses the warning also for the
 *          following line.
 * \warning This macro does not check the arguments, and it is therefore
 *          possible to write confusing declarations, it is recommended to use
 *          it only as suggested.
 *
 * \see YARP_DISABLE_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING,
 *      YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG
 */

///@}


#if defined(_MSC_VER)
# define YARP_WARNING_PUSH                             __pragma(warning(push))
# define YARP_WARNING_POP                              __pragma(warning(pop))
# define YARP_DISABLE_DEPRECATED_WARNING               __pragma(warning(disable:4996))
# define YARP_DISABLE_DLL_INTERFACE_WARNING            __pragma(warning(disable:4251))
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING           __pragma(warning(suppress:4251))
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG(x)    __pragma(warning(suppress:4251)) \
                                                       x
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS(...) __pragma(warning(suppress:4251)) \
                                                       __VA_ARGS__
#elif defined(__clang__)
# define YARP_WARNING_PUSH                             _Pragma("clang diagnostic push")
# define YARP_WARNING_POP                              _Pragma("clang diagnostic pop")
# define YARP_DISABLE_DEPRECATED_WARNING               _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
# define YARP_DISABLE_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG(x)    x
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS(...) __VA_ARGS__
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# define YARP_WARNING_PUSH                             _Pragma("GCC diagnostic push")
# define YARP_WARNING_POP                              _Pragma("GCC diagnostic pop")
# define YARP_DISABLE_DEPRECATED_WARNING               _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
# define YARP_DISABLE_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG(x)    x
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS(...) __VA_ARGS__
#else
# define YARP_WARNING_PUSH
# define YARP_WARNING_POP
# define YARP_DISABLE_DEPRECATED_WARNING
# define YARP_DISABLE_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARG(x)    x
# define YARP_SUPPRESS_DLL_INTERFACE_WARNING_ARGS(...) __VA_ARGS__
#endif


// Bug in GCC < 6
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43407
#if defined(__GNUC__) && (__GNUC__ < 6)
# define YARP_DISABLE_CLASS_ENUM_API_WARNING _Pragma("GCC diagnostic ignored \"-Wattributes\"")
#else
# define YARP_DISABLE_CLASS_ENUM_API_WARNING
#endif

#endif
