#ifndef __CYGWIN_H
#define __CYGWIN_H

#undef NDEBUG

#if defined(__linux)
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
#endif
#ifndef	_LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#endif


#if defined (_WIN32)
	// if we don't include winsock2 first, windows.h automatically includes winsock v1 which is mutually exclusive
	#include <winsock2.h>
#endif

#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>
#include <zlib.h>
#include <ctype.h>
#include <signal.h>
#include <malloc.h>

#ifdef __cplusplus
#include <string>  // for stl string
#include <algorithm>
#include <list>
#include <map>
#endif


#define ctol32(x)       (x)
#define ctol16(x)       (x) 

// WIN32: MSVC++ and MinGW
#if defined (_WIN32)
	// for MinGW ONLY
	#if defined (__MINGW32__)
//		#define _NO_OLDNAMES  1
//		#define NO_STRICT  1
//		#define strdup  _strdup
		#ifndef alloca
			#define alloca  __builtin_alloca
		#endif
	#else // for MSVC++ ONLY
		#define alloca  _alloca
	#endif /* __MINGW32__ */

	#define mtrace()	
	#define malloc_usable_size _msize

	#define CDONKEY	1

	// for both MSVC++ and MinGW
	typedef unsigned char      uint8_t ;
	typedef char                int8_t ;
	typedef unsigned short    uint16_t ;
	typedef short              int16_t ;
	typedef unsigned int      uint32_t ;
	typedef int                int32_t ;
	typedef unsigned __int64  uint64_t ;
	typedef __int64            int64_t ;

	#define HAVE_INET_ADDR  1
	#define HAVE_GETHOSTBYNAME  1
	#define HAVE_ATEXIT  1

	#undef HAVE_UNISTD_H
	#undef HAVE_GETADDRINFO    // can define for >= WinXP
//	#define WIN32_WINNT 0x501  // can set for >= WinXP
//	#include <ws2tcpip.h>      // can set for >= WinXP
	#define socklen_t int      // needed for < WinXP

	#include <windows.h>
	#include <time.h>
	#include <dos.h>
	#include <io.h>
	#include <process.h>
	#include "dirent_win.h"

	#define bzero(dat,len)  memset(dat,0,len)
	#define mkdir(dir,mode) (!::CreateDirectory(dir, NULL))
	#define getcwd(buf, size) _getcwd(buf, size)	//unused but good to know
	#define snprintf    _snprintf
//	#define vsnprintf   _vsnprintf			// unused but good to know
	#define strncasecmp	strncmp
	#define ftruncate(fd,len)	_chsize(fd,len)
	#define getpid()  _getpid()
	#define sleep(tsec)  ::Sleep(tsec*1000)
	#define __PRETTY_FUNCTION__ "PRETTY_FUNCTION"
	#define	dir_delim	'\\'
	// winsock error defines
	#define EHOSTUNREACH            WSAEHOSTUNREACH
	#define ECONNREFUSED            WSAECONNREFUSED
	#define ECONNRESET              WSAECONNRESET
	#define ETIMEDOUT		WSAETIMEDOUT
	#define ENOTCONN		WSAENOTCONN
	// file access
//	#define FD_open		_open
	#define FD_create(filename,oflag,pmode)	FD_open_DEBUG(__FILE__,__LINE__,filename,oflag,pmode)
	#define FD_open(filename,oflag)	FD_open_DEBUG(__FILE__,__LINE__,filename,oflag)
	inline int FD_open_DEBUG(char* file, int line, const char *filename, int oflag, int pmode=0)
	{
	int fd = _open(filename,oflag,pmode);
	  if( fd == -1 )
	  { printf("%s (%i):\n  Failed to open %s\n  %i : %s\n", file, line, filename, errno, strerror(errno)); }
	  else
	  { printf("Opened: (fd=%i) %s\n", fd, filename); }
	  fflush(stdout);
	  return fd;
	}
	#define FD_close	_close
	#define FD_fsync	_commit
	#define FD_write	_write
	#define FD_read		_read
	#define	FD_dup		_dup
	#define	FD_dup2		_dup2
	#define	FD_lseek	_lseek
	#define	FD_tell		_tell
	#define	send(s,m,l,f)			send(s,(const char*)m,l,f)
	#define recvfrom(s,b,l,f,src,len)	recvfrom(s,(char*)b,l,f,src,len)
	#define	recv(s,m,l,f)			recv(s,(char*)m,l,f)
	#define sendto(s,b,l,f,src,len)		sendto(s,(const char*)b,l,f,src,len)
#else	// NOT Windows
	#define FD_create	open
	#define FD_open		open
	#define FD_close	close
	#define FD_fsync	fsync
	#define FD_write	write
	#define FD_read		read
	#define	FD_dup		dup
	#define	FD_dup2		dup2
	#define	FD_lseek	lseek
	#define	FD_tell		tell
	#define O_BINARY	0
	#include "config.h"
	#include <sys/socket.h> //					(man socket,inet_addr)
	#include <netinet/in.h>	// Roman Shterenzon (BSD need this)	(man socket,inet_addr)
	#include <arpa/inet.h>	// by Frank Thieme			(man socket,inet_addr)
	#include <netdb.h>	// for DNS resolution			(man gethostbyname)
	#include <strings.h>
	#include <dirent.h>
	#include <unistd.h>
	#include <sys/ioctl.h>
	#include <sys/time.h>
	#include <sys/resource.h>
	#include <sys/stat.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <netinet/tcp.h>
	#include <sys/poll.h>
	#include <mcheck.h>
	#define dir_delim	'/'
	#define HAVE_SIGHUP	1
	#define HAVE_SIGINT	1
	#define HAVE_SIGPIPE	1
//	typedef unsigned long long uint64_t;
//	typedef long long int64_t;
	#define closesocket             close
	#define ioctlsocket             ioctl
#ifndef __FreeBSD__
	#define	bzero	__builtin_bzero
	#define strcmp	__builtin_strcmp
	#define	strchr 	__builtin_strchr        // Zeichen in String suchen
	#define strstr 	__builtin_strstr        // Zeichenkete in String suchen
	#define	strcpy 	__builtin_strcpy
	#define strncpy	__builtin_strncpy
	#define strlen	__builtin_strlen
//	#define	alloca	__builtin_alloca	// default
	#define printf	__builtin_printf
	#define memset 	__builtin_memset
	#define	memcmp 	__builtin_memcmp
	#define memcpy 	__builtin_memcpy
#endif
#endif

#ifndef HAVE_BZERO
	#define bzero(dat,len)	memset(dat,0,len)
#endif

#ifndef __FreeBSD__
	#define HAVE_ASYNCIO		1
#else
	#define HAVE_POLLIO		1
	#define	SOL_TCP	SOL_SOCKET
#endif

/*
# if __BYTE_ORDER == __BIG_ENDIAN
#       define ctol32(x)     __bswap_32 (x)
#       define ctol16(x)     __bswap_16 (x)
#endif
*/
#if __BYTE_ORDER == __LITTLE_ENDIAN
#       define ctol32(x)       (x)
#       define ctol16(x)       (x)
#endif
	
#define ASSERT(x)	{ bool assert_test = (x); if (!assert_test) { fflush(stdout); assert(x); } }
#define MALLOC	malloc
#define	STRDUP	strdup
#define REALLOC realloc	
/*
inline  void* MALLOC (size_t x) { void *ret = malloc(x); assert(ret != NULL); return ret; }
inline  char* STRDUP (const char *x) { char *ret = strdup(x); assert(ret != NULL); return ret; }
inline  void* REALLOC(void *ptr, size_t size) { void *ret = realloc(ptr, size); if (size != 0) assert(ret != NULL); return ret; }
*/
#endif // __CYGWIN_H
