// (c) 2005-2007 Electronic Arts Inc.
// (c) 2000-2004 Electronic Arts Inc. All Rights Reserved

// note gcc -dM -E dumps compiler predefines
/*
; ABSTRACT
;
; ifdef.cpp - tests defines and types
;
; SOURCE
@*/

#define _CRT_SECURE_NO_DEPRECATE
#ifdef _MANAGED
#using <mscorlib.dll>
#endif
#if defined(__SPU__) && defined(__CELLOS_LV2__)
#include <spu_printf.h> /* must be included for printf. */
#else
#include <stdio.h>
#endif

// for standard types
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#if defined(_WCHAR_T_DEFINED) || defined(__WCHAR_T_IS_KEYWORD)
#if defined(_MSC_VER)
#pragma warning(disable: 4514)  // unreferenced inline function has been removed
#pragma warning(disable: 4820)  // padding added after struct member
#pragma warning(disable: 4804)  // '<' : unsafe use of type 'bool' in operation
#include <typeinfo>
#endif
#include <wchar.h>
#endif
#if !defined(__PPCGEKKO__)
// This header is not on the Metrowerks Gamecube
#include <sys/types.h>
#endif
#if defined(__PPC__)
#include <stddef.h>
#endif

// sony sdk version
#if defined(__CELLOS_LV2__)
#include <sdk_version.h>
#endif

// linux types
#if !defined(__PPC__) && !defined(__SPU__)
#include <sys/stat.h>
#endif

#if defined(_MSC_VER)
#include <io.h>
#else
#include <unistd.h>
#endif
#if defined(__unix__) || defined(__APPLE__)
#include <pthread.h>
#endif

#if defined(__R5900) || defined(__R4000)
#include <libver.h>
#endif
#if defined(__SN_VER__)
// libsn.h for __SN_Libsn_version on PS2/Gamecube
#include <libsn.h>
#endif

#ifdef __SPU__
#define Print printf
#else
static void Print(const char *format,...);
#endif

// NOTE some headers deferred til later for printf purposes

int main(int argc, char **argv)
{
    Print("macros test 2007.10.12\n");
    Print( "argc %d\n",argc);
    int sizeargs=0;
    for (int i=0; i<argc; ++i)
    {
        Print( "argv[%d] %s",i,argv[i]);

        for (unsigned int j=0; j<strlen(argv[i]); ++j)
            Print( " %02x",argv[i][j]);

        Print( "\n");
        sizeargs += strlen(argv[i])+1;
    }
    Print( "sizeof argvs %d\n",sizeargs);

#ifdef __powerpc64__
    Print( "__powerpc64__ %d\n",__powerpc64__);  // cell
#endif
#ifdef __ALTIVEC__
    Print( "__ALTIVEC__ %d\n",__ALTIVEC__);  // cell
#endif
#ifdef __mips
    Print( "__mips %d\n",__mips);  // preferred
#endif
#ifdef _mips
    Print( "_mips %d\n",_mips);
#endif
#ifdef mips
    Print( "mips %d\n",mips);
#endif

#ifdef __R5900__
    Print( "__R5900__ %d\n",__R5900__);  // preferred
#endif
#ifdef __R5900
    Print( "__R5900 %d\n",__R5900);
#endif
#ifdef _R5900
    Print( "_R5900 %d\n",_R5900);
#endif
#ifdef R5900
    Print( "R5900 %d\n",R5900);
#endif

// psp sn
#ifdef __R4000
    Print( "__R4000 %d\n",__R4000);
#endif
#ifdef _R4000
    Print( "_R4000 %d\n",_R4000);
#endif
// __psp__ 0x000703
#ifdef __psp__
    Print( "__psp__ 0x%x\n",__psp__);
#endif

// xenon (Visual C)
#ifdef _M_PPC
    Print( "_M_PPC %d\n",_M_PPC);
#endif
// x86 (Visual C)
#ifdef _M_IX86
    Print( "_M_IX86 %d\n",_M_IX86);
#endif

#ifdef __MIPSEL__
    Print( "__MIPSEL__ %d\n",__MIPSEL__); // preferred
#endif
#ifdef __MIPSEL
    Print( "_MIPSEL %d\n",_MIPSEL);
#endif

#ifdef __ee__
    Print( "__ee__ %d\n",__ee__);
#endif

#ifdef __mips16
    Print( "__mips16\n");
#endif

#ifdef __unix__
    Print( "__unix__\n");
#endif
#ifdef _MSC_VER
    Print( "_MSC_VER %d\n",_MSC_VER);
#endif
#ifdef _MSC_FULL_VER
    Print( "_MSC_FULL_VER %d\n",_MSC_FULL_VER);
#endif
#ifdef _MANAGED
    Print( "_MANAGED\n");
#endif

#ifdef _XBOX
    Print( "_XBOX %d\n",_XBOX);
#endif
#ifdef _WIN32
    Print( "_WIN32 %d\n",_WIN32);
#endif
#ifdef _WIN64
    Print( "_WIN64 %d\n",_WIN64);
#endif
#ifdef _AMD64_
    Print( "_AMD64_ %d\n",_AMD64_);
#endif
#ifdef _M_AMD64
    Print( "_M_AMD64 %d\n",_M_AMD64);
#endif
#ifdef __x86_64__
    Print( "__x86_64__ %d\n",__x86_64__);
#endif

#ifdef _IX86
    Print( "_X86 %d\n",_IX86);
#endif
#ifdef applec
    Print( "applec %d\n",applec);
#endif
#ifdef powerc
    Print( "powerc %d\n",powerc);
#endif
#ifdef __powerc
    Print( "__powerc %d\n",__powerc);
#endif
#ifdef m68k
    Print( "m68k %d\n",m68k);
#endif
#ifdef __WATCOMC__
    Print( "__WATCOMC__ %d\n",__WATCOMC__);
#endif
#ifdef __cplusplus
    Print( "__cplusplus %d\n",__cplusplus);
#endif
#ifdef __PPCGEKKO__
    Print( "__PPCGEKKO__\n");
#endif
// for Wii
#ifdef __PPCBROADWAY__
    Print( "__PPCBROADWAY__\n");
#endif
#ifdef macintosh
    Print( "macintosh\n");
#endif
#ifdef __MWERKS__
    Print( "__MWERKS__ 0x%x\n",__MWERKS__); // 0x2200 for 2.2 or 1 if CW6 or less
#endif
#ifdef __INTEL__
    Print( "__INTEL__ %d\n",__INTEL__); // metrowerks on PC
#endif
#ifdef __i386__
    Print( "__i386__ %d\n",__i386__); // gcc on linux/windows
#endif
#ifdef __GNUC__
#if __GNUC__ >= 1
    Print( "__GNUC__ %d\n",__GNUC__);
#else
    Print( "__GNUC__\n");
#endif
#endif
#ifdef __GNUG__
#if __GNUG__ >= 1
    Print( "__GNUG__ %d\n",__GNUG__);
#else
    Print( "__GNUG__\n");
#endif
#endif

#ifdef __GNUC_MINOR__
    Print( "__GNUC_MINOR__ %d\n",__GNUC_MINOR__);
#endif
#ifdef __GNUC_PATCHLEVEL__
    Print( "__GNUC_PATCHLEVEL__ %d\n",__GNUC_PATCHLEVEL__);
#endif

#ifdef __IEEE_LITTLE_ENDIAN
    Print( "__IEEE_LITTLE_ENDIAN\n");
#endif

#ifdef __IEEE_BIG_ENDIAN
    Print( "__IEEE_BIG_ENDIAN\n");
#endif

#ifdef __BIG_ENDIAN__
    Print( "__BIG_ENDIAN__ %d\n",__BIG_ENDIAN__);
#endif
#ifdef __LITTLE_ENDIAN__
    Print( "__LITTLE_ENDIAN__ %d\n",__LITTLE_ENDIAN__);
#endif
#ifdef __BIG_ENDIAN
    Print( "__BIG_ENDIAN %d\n",__BIG_ENDIAN);
#endif
#ifdef __LITTLE_ENDIAN
    Print( "__LITTLE_ENDIAN %d\n",__LITTLE_ENDIAN);
#endif
#ifdef LITTLE_ENDIAN
    Print( "LITTLE_ENDIAN %d\n",LITTLE_ENDIAN);
#endif
#ifdef BIG_ENDIAN
    Print( "BIG_ENDIAN %d\n",BIG_ENDIAN);
#endif
#ifdef BYTE_ORDER
    Print( "BYTE_ORDER %d\n",BYTE_ORDER);
#endif

#ifdef REAL_BIGENDIAN
    Print( "REAL_BIGENDIAN %d\n",REAL_BIGENDIAN);
#endif
#ifdef __STDC__
    Print( "__STDC__ %d\n",__STDC__);
#endif
#ifdef __STDC_VERSION__
    Print( "__STDC_VERSION__\n");
#endif
#ifdef __VERSION__
    Print( "__VERSION__ %s\n",__VERSION__);
#endif
#ifdef __SN_VER__
    Print( "__SN_VER__ %d (0x%x)\n",__SN_VER__,__SN_VER__);
#endif
#ifdef __SNC__
    Print( "__SNC__ %d\n",__SNC__);
#endif
#ifdef __EDG_VERSION__
    Print( "__EDG_VERSION__ %d\n",__EDG_VERSION__);
#endif
#ifdef __EDG__
    Print( "__EDG__ %d\n",__EDG__);
#endif
#ifdef __xlc__
    Print( "__xlc__ %d\n",__xlc__);
#endif
#ifdef __xlC__
    Print( "__xlC__ %d\n",__xlC__);
#endif
#ifdef __IBMC__
    Print( "__IBMC__ %d\n",__IBMC__);
#endif
#ifdef __IBMCPP__
    Print( "__IBMCPP__ %d\n",__IBMCPP__);
#endif
#ifdef __CELLOS_LV2__
    Print( "__CELLOS_LV2__ %d\n",__CELLOS_LV2__);
#endif
#ifdef __CONTROL__
    Print( "__CONTROL__ %d\n",__CONTROL__);
#endif
#ifdef SCE_LIBRARY_VERSION
    Print( "SCE_LIBRARY_VERSION 0x%x\n",SCE_LIBRARY_VERSION);
#endif
#ifdef CELL_SDK_VERSION
    Print( "CELL_SDK_VERSION 0x%x\n",CELL_SDK_VERSION);
#endif
#ifdef __APPLE__
    Print( "__APPLE__\n");
#endif
#ifdef __APPLE_CC__
    Print( "__APPLE_CC__ %d\n",__APPLE_CC__);
#endif
#ifdef __PPC__
    Print( "__PPC__ %d\n",__PPC__);
#endif
#ifdef __PPC64__
    Print( "__PPC64__ %d\n",__PPC64__);
#endif
#ifdef __SPU__
    Print( "__SPU__ %d\n",__SPU__);
#endif
#if defined(__PU__)
    Print( "__PU__ %d\n",__PU__);
#endif
#if defined(__PPU__)
    Print( "__PPU__ %d\n",__PPU__);
#endif
#ifdef sparc
    Print( "sparc\n");
#endif
#ifdef __FUNCTION__
    Print( "__FUNCTION__ %s\n",__FUNCTION__);  // visual c
#endif
#ifdef __func__
    Print( "__func__ %s\n",__func__); // gcc
#endif
#ifdef __FUNC__
    Print( "__FUNC__ %s\n",__FUNC__); // borland
#endif
#ifdef __PRETTY_FUNCTION__
    Print( "__PRETTY_FUNCTION__ %s\n",__PRETTY_FUNCTION__);  // gcc c++
#endif
// visual c MTd
#ifdef _DEBUG
    Print( "_DEBUG %d\n",_DEBUG);
#endif
// visual c
#ifdef NDEBUG
    Print( "NDEBUG %d\n",NDEBUG);
#endif
// old visual c 7.0 /Od uses _FAST
#ifdef _FAST
    Print( "_FAST %d\n",_FAST);
#endif
// old visual c 7.0 /Od uses _FAST_
#ifdef __FAST__
    Print( "__FAST__ %d\n",__FAST__);
#endif
// visual c 6.0 /Od uses _QC
#ifdef _QC
    Print( "_QC %d\n",_QC);
#endif

// gcc define for bits per byte... must be 8
#ifdef _BITS_BYTE
    Print( "_BITS_BYTE %d\n",_BITS_BYTE);
#endif
#ifdef _INTEGRAL_MAX_BITS
    Print( "_INTEGRAL_MAX_BITS %d\n",_INTEGRAL_MAX_BITS);
#endif
#ifdef __USE_LARGEFILE64
    Print( "__USE_LARGEFILE64 %d\n",__USE_LARGEFILE64);
#endif
#ifdef O_LARGEFILE
    Print( "O_LARGEFILE %d\n",O_LARGEFILE);
#endif
#ifdef O_BINARY
    Print( "O_BINARY %d\n",O_BINARY);  // metrowerks & icl/cl on windows have it... some others don't
#endif
#ifdef _WCHAR_T_DEFINED
    Print( "_WCHAR_T_DEFINED\n");  // /Zc:wchar_t
#endif
#ifdef __WCHAR_T_IS_KEYWORD
    Print( "__WCHAR_T_IS_KEYWORD\n");  // SNC /X+=wchar_t
#endif
#ifdef __WCHAR_MAX__
    Print( "__WCHAR_MAX__ %d\n", __WCHAR_MAX__);
#endif
#ifdef WCHAR_MAX
    Print( "WCHAR_MAX %d\n", WCHAR_MAX);
#endif
#ifdef _BOOL_DEFINED
    Print( "_BOOL_DEFINED\n");  // SNC /X+=bool
#endif
#ifdef __BOOL_IS_KEYWORD
    Print( "__BOOL_IS_KEYWORD\n");  // SNC /X+=wchar_t
#endif
#ifdef _C99
    Print( "_C99\n");
#endif
#ifdef __USE_ISOC99
    Print( "__USE_ISOC99\n");
#endif
#ifdef __ICL
    Print( "__ICL %d\n",__ICL);
#endif
#ifdef __ICC
    Print( "__ICC %d\n",__ICC);
#endif

// visual c
// for ps3 32 vs 64 bit compilers
#ifdef __LP32__
    Print( "__LP32__ %d\n",__LP32__);
#endif
#ifdef __LP64__
    Print( "__LP64__ %d\n",__LP64__);
#endif

    Print( "((unsigned char)-1) %u\n",((unsigned char)-1));
    Print( "((unsigned short)-1) %u\n",((unsigned short)-1));
    Print( "((unsigned int)-1) %u\n",((unsigned int)-1));
    Print( "((unsigned long)-1) %lu\n",((unsigned long)-1));
#ifdef _MSC_FULL_VER
    Print( "((unsigned long long)-1) %I64u\n",((unsigned long long)-1));
    Print( "((unsigned __int64)-1) %I64u\n",((unsigned __int64)-1));
#else
    Print( "((unsigned long long)-1) %llu\n",((unsigned long long)-1));
#endif
    Print( "((wchar_t)-1) %u\n",((wchar_t)-1));


    struct vcharstruct
    { char bar; virtual int MagicNumber() { return 1;}  virtual ~vcharstruct() {} };
    Print( "sizeof(struct vcharstruct) %d\n",sizeof( struct vcharstruct ));

    struct charvcharstruct : public vcharstruct { char foo; };
    Print( "sizeof(struct charvcharstruct) %d\n",sizeof( struct charvcharstruct ));

    struct charstruct { char bar;  };
    Print( "sizeof(struct charstruct) %d\n",sizeof( struct charstruct ));

    struct vcharcharstruct : public charstruct { char foo; virtual int MagicNumber() { return 1; } virtual ~vcharcharstruct() {}  };
    Print( "sizeof(struct vcharcharstruct) %d\n",sizeof( struct vcharcharstruct ));

#if 0
    // same on gcc and vc
#ifdef __GNUC__
    struct charalign
    { char foo __attribute__ ((aligned (16)));
      char bar;
    };
#endif
#ifdef _MSC_FULL_VER
    struct charalign
    { __declspec(align(16)) char foo;
      char bar;
    };
#endif
#if defined(__GNUC__) || defined(_MSC_FULL_VER)
    Print( "sizeof(struct charalignchar) %d\n",sizeof( struct charalign ));
    struct charalignchar :  public charalign
    { char phoo;
    };
    Print( "sizeof(struct charalignchar) %d\n",sizeof( struct charalignchar ));
#endif
#endif

    enum enumtype
    {
        ENUMNEG = -1,
        ENUMPOS = 1
    };

    Print( "sizeof(size_t) %d\n",sizeof(size_t));
#if !defined(__SPU__) && !defined(__PU__)
    Print( "sizeof(fpos_t) %d\n",sizeof(fpos_t));
#endif
    Print( "sizeof(off_t) %d\n",sizeof(off_t));
#ifdef off64_t
    Print( "off64_t\n");
#endif
#ifdef WCHAR
    Print( "sizeof(WCHAR) %d\n",sizeof(WCHAR));
#endif
    Print( "sizeof(wchar_t) %d\n",sizeof(wchar_t));
#ifdef __off64_t
    Print( "sizeof(__off64_t) %d\n",sizeof(__off64_t));
#endif

#if 0
#ifdef _MSC_FULL_VER
    Print( "sizeof(__m128) %d\n",sizeof(__m128));  // 4 floats
    __m128 a={1.0f,2.0f,3.0f,4.0f};
    Print128(42,a);
#endif
#endif

#if __cplusplus
    Print( "sizeof(bool) %d\n",sizeof(bool));
#endif

//    Print( "sizeof(ENUMNEG) %d\n",sizeof(ENUMNEG));
//    Print( "sizeof(ENUMPOS) %d\n",sizeof(ENUMPOS));
    Print( "sizeof(enum) %d\n",sizeof(enumtype));

    Print( "sizeof(void *) %d\n",sizeof(void *));
    Print( "sizeof(void (*)(void)) %d\n",sizeof(void (*)(void)));
    Print( "sizeof(&main) %d\n",sizeof(&main));
    Print( "sizeof(char) %d\n",sizeof(char));
    Print( "sizeof(short) %d\n",sizeof(short));
    Print( "sizeof(int) %d\n",sizeof(int));
    Print( "sizeof(long) %d\n",sizeof(long));
    Print( "sizeof(long long) %d\n",sizeof(long long));
#ifdef _C99
    Print( "sizeof(int64_t) %d\n",sizeof(int64_t));
#endif

    Print( "sizeof(float) %d\n",sizeof(float));
    Print( "sizeof(double) %d\n",sizeof(double));
    Print( "sizeof(long double) %d\n",sizeof(long double));

#if defined(_MSC_VER)
    Print( "sizeof(__int64) %d\n",sizeof(__int64));

    Print( "sizeof(0i32) %d\n",sizeof(0i32));
    Print( "sizeof(0i16) %d\n",sizeof(0i16));
#endif
    Print( "sizeof('a') %d\n",sizeof('a'));
    Print( "sizeof('a'<<8) %d\n",sizeof('a'<<8));
    Print( "sizeof(L'\\0') %d\n",sizeof(L'\0'));
//  Print( "sizeof(0L) %d\n",sizeof(0L));
//  Print( "sizeof(0LL) %d\n",sizeof(0LL));

#if defined(_WCHAR_T_DEFINED) || defined(__WCHAR_T_IS_KEYWORD)
    {
        unsigned short string[4]={0x4142,0x4344,0,0};
        int wlen = static_cast<int>(wcslen((wchar_t *) &string[0]));
        int sizeof_libc_wchar_t = wlen?(4/(wlen)):0;

        if (sizeof_libc_wchar_t!=sizeof(wchar_t))
            Print("libc wchar_t and compiler wchar_t don't match\n");

        Print( "sizeof_libc_wchar_t %d\n",sizeof_libc_wchar_t);
    }
#endif

    // done as ternary to avoid 'conditional is constant'


    Print( "bool %s\n",    ((bool)(-1) < 0)  ? "signed" : "unsigned" );
    Print( "char %s\n",    ((char)(-1) < 0)  ? "signed" : "unsigned" );
    Print( "wchar_t %s\n", ((wchar_t)(-1) < 0)  ? "signed" : "unsigned" );
    Print( "enum %s\n", ((enumtype)(-1) < 0)  ? "signed" : "unsigned" );
    Print( "enum %s\n", ((enumtype)(0x80000000) < 0)  ? "signed" : "unsigned" );
//  Print( "L'\\177777') %s\n",(L'\177777' < 0) ? "signed" : "unsigned" );
//  Print( "L'\\37777777777') %s\n",(L'\37777777777' < 0) ? "signed" : "unsigned" );

    {
        volatile unsigned short buf=1;
        if (*(volatile unsigned char *) &buf)
            Print("little endian\n");
        else
            Print("big endian\n");
    }

    Print( "strlen(\"\\n\") %d\n",strlen("\n"));
//    Print( "wcslen(L\"Hello\") %d\n",wcslen(L"Hello"));
//    Print( "sizeof(L\"Hello\") %d\n",sizeof(L"Hello"));

#ifdef __unix__
    Print( "sizeof(pthread_t) %d\n", sizeof(pthread_t));
    Print( "sizeof(pthread_mutex_t) %d\n", sizeof(pthread_mutex_t));
#endif

#ifdef INT64
    Print( "sizeof(INT64) %d\n",sizeof(INT64));
#endif
#ifdef INT128
    Print( "sizeof(INT128) %d\n",sizeof(INT128));
#endif


#if 0
    {
        wchar_t x;
        Print("The type of x is %s", type_info(wchar_t).name());
    }
#endif


        struct ARGB
        {
            char b,g,r,a;
        };
        Print( "offsetof(ARGB.a) %d\n",offsetof(ARGB,a));

#if 0
    {
#define FALSE 0
#define TRUE !FALSE

        Print("The type of FALSE is %s\n", typeid(FALSE).name());
        Print("The type of TRUE is %s\n", typeid(TRUE).name());
    }
        struct boolbitfield
        {
            bool onebitmember:1;
        };
        Print( "sizeof(bool:1 bitfield) %d\n",sizeof(boolbitfield));

        struct ucharbitfield
        {
            unsigned char onebitmember:1;
        };
        Print( "sizeof(uchar:1 bitfield) %d\n",sizeof(boolbitfield));

        struct intboolbitfield
        {
            int  twobitmember:8;
            bool onebitmember:1;
        };
        Print( "sizeof(int:8+bool:1 bitfield) %d\n",sizeof(intboolbitfield));

        struct ucharboolbitfield
        {
            unsigned char twobitmember:8;
            bool onebitmember:1;
        };
        Print( "sizeof(uchar:8+bool:1 bitfield) %d\n",sizeof(ucharboolbitfield));
#endif

#if 0
#if defined(_MSC_VER)
    const __int64 max64 = 0x7fffffffffffffff;
    Print("0x7fffffffffffffff is %I64d\n", max64);
#else
    const long long max64 = 0x7fffffffffffffffLL;
    Print("0x7fffffffffffffff is %lld\n", (long long) max64);   // note that long long should be at least 64 bits, but might be more
#endif
#endif


#if defined(__SN_VER__)
//  Print("libsn version = %d\n",__SN_Libsn_version[0]);
#endif

#if defined(__PPU__) || defined(__R5900)
    Print("\32"); // ps2/ps3 ^Z to exits ps3run
#endif

#if defined(_XBOX)
    for (;;) ;
#else
    return 0;
#endif
}



#if defined(_XBOX)
#pragma warning(push)
#pragma warning(disable: 4820) // byte padding added after member
#pragma warning(disable: 4668) // macro referenced by not defined
#include <xtl.h>        // OutputDebugString
#pragma warning(pop)
#endif

#if (defined(__SN__) && defined(__PPC__)) || defined(__PPCGEKKO__)
// needed for OSReport()
#include "dolphin.h"
#endif

#ifndef __SPU__
static void Print(const char *format,...)
{
    va_list val;
    char buffer[512];

    if (format)
    {
        va_start(val,format);
        vsprintf(buffer, format, val);
        va_end(val);
    }
    else
        buffer[0] = '\0';

#if defined(_XBOX)
    OutputDebugString(buffer);
#elif defined(GC)
    OSReport(buffer);
#else
    printf("%s",buffer);
#endif
}
#endif

// END ABSTRACT
