/*
 * libmowgli: A collection of useful routines for programming.
 * machine.h: Defines to discover what machine we're on easily
 *
 * Copyright (c) 2012, 2013 Patrick McFarland <pmcfarland@adterrasperaspera.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/* Machine environment specific macros, mostly sourced from this URL:
 * http://sourceforge.net/apps/mediawiki/predef/
 *
 * Please note: Just because a compiler, CPU, or OS is listed in this file,
 * that doesn't mean that it is supported by libmowgli. libmowgli requires
 * a 32-bit or higher CPU and an OS that supports a supported mutex and
 * thread scheme (if you intend on having functional multithreaded
 * operation).
 */

#ifndef MOWGLI_SRC_LIBMOWGLI_PLATFORM_MACHINE_H_INCLUDE_GUARD
#define MOWGLI_SRC_LIBMOWGLI_PLATFORM_MACHINE_H_INCLUDE_GUARD 1

#if defined __clang__
#  define MOWGLI_COMPILER_CLANG
#  define MOWGLI_COMPILER clang
#elif defined __INTEL_COMPILER || defined __ICC || defined __ICL
#  define MOWGLI_COMPILER_ICC
#  define MOWGLI_COMPILER icc
#elif defined __CC_ARM
#  define MOWGLI_COMPILER_ARM
#  define MOWGLI_COMPILER arm
#elif defined __xlc__ || defined __xlC__
#  define MOWGLI_COMPILER_IBM
#  define MOWGLI_COMPILER ibm
#elif defined __SUNPRO_C || defined __SUNPRO_CC
#  define MOWGLI_COMPILER_SUN
#  define MOWGLI_COMPILER sun
#elif defined __GNUC__
#  define MOWGLI_COMPILER_GCC
#  define MOWGLI_COMPILER gcc
#elif defined _MSC_VER
#  define MOWGLI_COMPILER_MSVC
#  define MOWGLI_COMPILER msvc
#else
#  define MOWGLI_COMPILER_UNKNOWN
#  define MOWGLI_COMPILER unknown
#endif

#if defined __GNUC__
#  define MOWGLI_COMPILER_GCC_COMPAT
#  define MOWGLI_COMPILER_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#else
#  define MOWGLI_COMPILER_GCC_VERSION (0)
#endif

#if defined __amd64__ || defined __amd64 || defined __x86_64__ || defined __x86_64 || defined _M_X64 || defined _M_AMD64
#  define MOWGLI_CPU_X86_64
#  define MOWGLI_CPU x86_64
#  define MOWGLI_CPU_BITS_64
#  define MOWGLI_CPU_BITS 64
#  define MOWGLI_CPU_ENDIAN_LITTLE
#  define MOWGLI_CPU_ENDIAN little
#elif defined __i386__ || defined __i386 || defined __IA32__ || defined _M_IX86 || defined __X86__ || defined _X86__ || defined __I86__
#  define MOWGLI_CPU_X86
#  define MOWGLI_CPU x86
#  define MOWGLI_CPU_BITS_32
#  define MOWGLI_CPU_BITS 32
#  define MOWGLI_CPU_ENDIAN_LITTLE
#  define MOWGLI_CPU_ENDIAN little
#elif defined __arm__ || defined __TARGET_ARCH_ARM || defined _ARM
#  if defined __thumb__ || defined __TARGET_ARCH_THUMB
#    define MOWGLI_CPU_ARM_THUMB
#  endif
#  define MOWGLI_CPU_ARM
#  define MOWGLI_CPU arm
#  define MOWGLI_CPU_BITS_32
#  define MOWGLI_CPU_BITS 32

// ARM can be either endian
#elif defined __hppa__ || defined __HPPA__ || defined __hppa
#  if defined _PA_RISC2_0 || defined __HPPA20__ || defined __RISC2_0__
#    define MOWGLI_CPU_HPPA20
#    define MOWGLI_CPU hppa20
#    define MOWGLI_CPU_BITS_64
#    define MOWGLI_CPU_BITS 64
#  else
#    define MOWGLI_CPU_HPPA10
#    define MOWGLI_CPU hppa10
#    define MOWGLI_CPU_BITS_32
#    define MOWGLI_CPU_BITS 32
#  endif
#  define MOWGLI_CPU_ENDIAN_BIG
#  define MOWGLI_CPU_ENDIAN big
#elif defined __ia64__ || defined __IA64__ || defined _M_IA64 || defined __ia64 || defined __itanium__
#  define MOWGLI_CPU_ITANIUM
#  define MOWGLI_CPU itanium
#  define MOWGLI_CPU_BITS_64
#  define MOWGLI_CPU_BITS 64

// Itanium can be either endian
#elif defined __mips__ || defined mips || defined __mips || defined __MIPS__
#  if defined __mips64 || defined __mips64__
#    define MOWGLI_CPU_MIPS64
#    define MOWGLI_CPU mips64
#    define MOWGLI_CPU_BITS_64
#    define MOWGLI_CPU_BITS 64
#  else
#    define MOWGLI_CPU_MIPS
#    define MOWGLI_CPU mips
#    define MOWGLI_CPU_BITS_32
#    define MOWGLI_CPU_BITS 32
#  endif

// MIPS can be either endian
#elif defined __powerpc || defined __powerpc__ || defined __POWERPC__ || defined __ppc__ || defined _M_PPC
#  if defined __ppc64__ || defined __PPC64__
#    define MOWGLI_CPU_POWERPC64
#    define MOWGLI_CPU powerpc64
#    define MOWGLI_CPU_BITS_64
#    define MOWGLI_CPU_BITS 64
#  else
#    define MOWGLI_CPU powerpc
#    define MOWGLI_CPU_BITS_32
#    define MOWGLI_CPU_BITS 32
#  endif
#  define MOWGLI_CPU_POWERPC

// PowerPC can be either endian
#elif defined __sparc__ || defined __sparc
#  if defined __sparcv9 || defined __sparc64 || defined __sparc64__
#    define MOWGLI_CPU_SPARC64
#    define MOWGLI_CPU sparc64
#    define MOWGLI_CPU_BITS_64
#    define MOWGLI_CPU_BITS 64
#  else
#    define MOWGLI_CPU_SPARC
#    define MOWGLI_CPU sparc
#    define MOWGLI_CPU_BITS_32
#    define MOWGLI_CPU_BITS 32
#  endif
#  define MOWGLI_CPU_ENDIAN_BIG
#  define MOWGLI_CPU_ENDIAN big
#elif defined __alpha || defined __alpha__ || defined _M_ALPHA
#  define MOWGLI_CPU_ALPHA
#  define MOWGLI_CPU alpha
#  define MOWGLI_CPU_BITS_64
#  define MOWGLI_CPU_BITS 64
#  define MOWGLI_CPU_ENDIAN_LITTLE
#  define MOWGLI_CPU_ENDIAN little
#elif defined __avr32__ || defined __AVR32__
#  define MOWGLI_CPU_AVR32
#  define MOWGLI_CPU avr
#  define MOWGLI_CPU_BITS_32
#  define MOWGLI_CPU_BITS 32
#  define MOWGLI_CPU_ENDIAN_LITTLE
#  define MOWGLI_CPU_ENDIAN little
#elif defined __sh__ || defined __SH__
#  define MOWGLI_CPU_SuperH
#  define MOWGLI_CPU superh
#  define MOWGLI_CPU_BITS_32
#  define MOWGLI_CPU_BITS 32

// SyoerH can be either endian
#endif

#ifndef MOWGLI_CPU
#  define MOWGLI_CPU_UNKNOWN
#  define MOWGLI_CPU unknown
#endif

#ifndef MOWGLI_CPU_BITS
#  if defined _LP64 || defined __LP64
#    define MOWGLI_CPU_BITS 64
#    define MOWGLI_CPU_BITS_64
#  else
#    define MOWGLI_CPU_BITS 32
#    define MOWGLI_CPU_BITS_32
#  endif
#endif

#if defined __linux || defined __linux__
#  define MOWGLI_OS_LINUX
#  define MOWGLI_OS linux
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#elif defined __APPLE__
#  define MOWGLI_OS_OSX
#  define MOWGLI_OS osx
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  define MOWGLI_OS_BSD_TYPE

#  ifdef MOWGLI_CPU_POWERPC
#    define MOWGLI_CPU_ENDIAN_BIG
#    define MOWGLI_CPU_ENDIAN big
#  endif
#elif defined __WINDOWS__ || defined _WIN32 || defined __WIN32__ || defined __TOS_WIN__
#  if defined _WIN64
#    define MOWGLI_OS_WIN64
#    define MOWGLI_OS win64
#  else
#    define MOWGLI_OS_WIN32
#    define MOWGLI_OS win32
#  endif
#  define MOWGLI_OS_WIN
#  define MOWGLI_OS_THREADS_WIN
#  define MOWGLI_OS_THREADS win
#  define MOWGLI_OS_MUTEX_WIN
#  define MOWGLI_OS_MUTEX win

#  if defined __CYGWIN__
#    define MOWGLI_OS_WIN_CYGWIN
#  elif defined __MINGW32__
#    define MOWGLI_OS_WIN_MINGW
#  endif

#  if defined MOWGLI_CPU_POWERPC || defined MOWGLI_CPU_MIPS || defined MOWGLI_CPU_ITANIUM
#    define MOWGLI_ENDIAN_CPU_LITTLE
#  endif
#elif defined __NetBSD__ || defined __OpenBSD__ || defined __FreeBSD__ || defined __bsdi__ || defined __DragonFly__ || defined BSD || defined _SYSTYPE_BSD
#  define MOWGLI_OS_BSD
#  define MOWGLI_OS bsd
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  define MOWGLI_OS_BSD_TYPE
#elif defined __GNU__
#  define MOWGLI_OS_HURD
#  define MOWGLI_OS hurd
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#elif defined sco || defined __sco
#  define MOWGLI_OS_SCO
#  define MOWGLI_OS sco
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  define MOWGLI_OS_UNIX_TYPE
#elif defined sun || defined __sun
#  define MOWGLI_OS_SOLARIS
#  define MOWGLI_OS solaris
#  define MOWGLI_OS_THREADS_SOLARIS
#  define MOWGLI_OS_THREADS solaris
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  define MOWGLI_OS_UNIX_TYPE
#  if defined MOWGLI_CPU_POWERPC
#    define MOWGLI_CPU_ENDIAN_LITTLE
#    define MOWGLI_CPU_ENDIAN little
#  endif
#elif defined _hpux || defined hpux || defined __hpux
#  define MOWGLI_OS_HPUX
#  define MOWGLI_OS hpux
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  define MOWGLI_OS_UNIX_TYPE
#  if defined MOWGLI_CPU_ITANIUM
#    define MOWGLI_CPU_ENDIAN_BIG
#    define MOWGLI_CPU_ENDIAN big
#  endif
#elif defined __QNX__ || defined __QNXNTO__
#  define MOWGLI_OS_QNX
#  define MOWGLI_OS qnx
#  define MOWGLI_OS_THREADS_QNX
#  define MOWGLI_OS_THREADS qnx
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#elif defined __vms || defined __VMS
#  define MOWGLI_OS_THREADS_POSIX
#  define MOWGLI_OS_THREADS posix
#  define MOWGLI_OS_MUTEX_POSIX
#  define MOWGLI_OS_MUTEX posix
#  if defined MOWGLI_CPU_ITANIUM
#    define MOWGLI_CPU_ENDIAN_LITTLE
#    define MOWGLI_CPU_ENDIAN little
#  endif
#endif

#ifndef MOWGLI_OS
#  if defined __unix__ || __unix || unix
#    define MOWGLI_OS_UNIX
#    define MOWGLI_OS unix
#    define MOWGLI_OS_THREADS_POSIX
#    define MOWGLI_OS_THREADS posix
#    define MOWGLI_OS_MUTEX_POSIX
#    define MOWGLI_OS_MUTEX posix
#    define MOWGLI_OS_UNIX_TYPE
#  endif
#  define MOWGLI_OS_UNKNOWN
#  define MOWGLI_OS unknown
#  warning OS unsupported/unknown
#endif

#ifndef MOWGLI_OS_THREADS
#  define MOWGLI_OS_THREADS_NULL
#  define MOWGLI_OS_THREADS null
#endif

#ifndef MOWGLI_OS_MUTEX
#  define MOWGLI_OS_MUTEX_NULL
#  define MOWGLI_OS_MUTEX null
#endif

#ifndef MOWGLI_CPU_ENDIAN
#  if defined __BIG_ENDIAN__ || defined __ARMEB__ || defined __THUMBEB__ || defined _MIPSEB || defined __MIPSEB || defined __MIPSEB__ || __BYTE_ORDER == __BIG_ENDIAN
#    define MOWGLI_CPU_ENDIAN_BIG
#    define MOWGLI_CPU_ENDIAN big
#  elif defined __LITTLE_ENDIAN__ || defined __ARMEL__ || defined __THUMBEL__ || defined _MIPSEL || defined __MIPSEL || defined __MIPSEL__ || __BYTE_ORDER == __LITTLE_ENDIAN
#    define MOWGLI_CPU_ENDIAN_LITTLE
#    define MOWGLI_CPU_ENDIAN little
#  else
#    warning CPU endianness unknown, some functions of libmowgli will not work
#  endif
#endif

#endif /* MOWGLI_SRC_LIBMOWGLI_PLATFORM_MACHINE_H_INCLUDE_GUARD */
