/*****************************************************************************
 * $LastChangedDate: 2010-01-28 11:59:08 -0500 (Thu, 28 Jan 2010) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Operating-system and system-specific headers/defines.
 *//*
 * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef BASE_SYS_HH
#define BASE_SYS_HH 1

//==============================================================================
// Include header files.
// This is included very early so it has to be independent of other base/*.hh.

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

// Try to define the OS_* defines which may have been pre-defined by make files.
#if ! defined(OS_LINUX) && (defined(linux) || defined(__linux__))
#   define OS_LINUX 1
#elif ! defined(OS_FREEBSD) && defined(__FreeBSD__)
#   define OS_FREEBSD 1
#elif ! defined(OS_APPLE) && defined(__APPLE__)
#   define OS_APPLE 1
#elif ! defined(OS_WINDOWS) && defined(_MSC_VER)
#   define OS_WINDOWS 1  // native Windows
#elif ! defined(OS_CYGWIN) && defined(__CYGWIN__)
#   define OS_CYGWIN 1
#endif

// --- ANSI C / POSIX headers ---
// NOTE: Do not include standard C headers, rather,
// include C++'s C-compatible headers at base/cc.hh.
#include <cstring>
#include <sys/types.h>

//==============================================================================
// Compiler:

// Testing GCC_VERSION is tricky.
//
// Test if gcc is version 4.1 or higher:
// GCC_VERSION >= 40100 // right: 2 digits for minor/micro fields!
// GCC_VERSION >= 41000 // wrong
//
// Test if gcc is below gcc 3.0 requires two conditions:
// GCC_VERSION > 0 && GCC_VERSION < 30000  // right
//
#if defined(__GNUC__)
#   if defined(__GNUC_PATCHLEVEL__)
#       define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
#   else
#       define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100)
#   endif
#else
#   define GCC_VERSION 0
#endif

// Kludges for GCC.
#if defined(__GNUC__)
    #if GCC_VERSION < 30400
    #   error "gcc 3.4 or later is required"
    #elif GCC_VERSION < 40000
    // Workaround: gcc 3.4 has problems with friends that are nested classes
    // and friend class eponyms.
    #   define private public
    #   define protected public
    #endif
#endif

// Kludges for VC++.
#if OS_WINDOWS
#define and &&
#define or ||
#define not !
#undef uint
#define uint unsigned int
#pragma warning(disable:4005)  // suppress macro redefinition
#pragma warning(disable:4355)  // "this" in base init list (ok if just pointer stored)
#endif

// To overcome VC++ warning 4800 (left enabled as it has caught severe bugs).
#define BOOL_CAST( EXPR ) ((EXPR) != 0)

//==============================================================================
// CPU:

// CPU endianness.
#if BYTE_ORDER == LITTLE_ENDIAN
#   define CPU_LITTLE_ENDIAN 1
#elif BYTE_ORDER == BIG_ENDIAN
#   define CPU_BIG_ENDIAN 1
#endif  // else don't cause error here

// CPU basic architecture (for word size use CPU_32 or CPU_64).
#if defined(_X86_)||defined(__x86__)||defined(i386)||defined(__i386__)||defined(__x86_64__)||defined(__x86_64)
#   define CPU_X86 1
#elif defined(__ppc__)||defined(__ppc64__)
#   define CPU_PPC 1
#endif

// CPU architecture bit size.
#if __LP64__
#   define CPU_64 1
#   define CPU_SIZE 64
#else
#   define CPU_32 1
#   define CPU_SIZE 32
#endif  // else don't cause error here

#endif // BASE_SYS_HH
