#include <config.h>
#include <platform.h>
#include <sys/timeb.h>
#include <stdlib.h>
#include <fcntl.h>
#include <java/lang/ArithmeticException.h>
#include <java/lang/UnsupportedOperationException.h>
#include <java/io/IOException.h>
#include <java/net/SocketException.h>
#include <java/util/Properties.h>
static LONG CALLBACK
win32_exception_handler (LPEXCEPTION_POINTERS e)
{
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
_Jv_ThrowNullPointerException();
else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
throw new java::lang::ArithmeticException;
else
return EXCEPTION_CONTINUE_SEARCH;
}
static char exec_name[MAX_PATH];
const char *_Jv_ThisExecutable (void)
{
return exec_name;
}
#ifdef MINGW_LIBGCJ_UNICODE
jstring
_Jv_Win32NewString (LPCTSTR pcsz)
{
return JvNewString ((jchar*) pcsz, _tcslen (pcsz));
}
#else
static int nativeToUnicode(LPCSTR pcsz, jstring jstr = 0)
{
jchar* buf = 0;
int len = 0;
if (jstr)
{
len = jstr->length();
buf = JvGetStringChars(jstr);
}
return ::MultiByteToWideChar(GetACP(), 0, pcsz,
strlen(pcsz), (LPWSTR) buf, len);
}
static int unicodeToNative(jstring jstr, LPSTR buf, int buflen)
{
return ::WideCharToMultiByte(GetACP(), 0, (LPWSTR) JvGetStringChars(jstr),
jstr->length(), buf, buflen, NULL, NULL);
}
static int unicodeToNative(jstring jstr)
{
return unicodeToNative(jstr, 0, 0);
}
jstring
_Jv_Win32NewString (LPCTSTR pcsz)
{
int len = nativeToUnicode(pcsz);
jstring jstr = JvAllocString(len);
nativeToUnicode(pcsz, jstr);
return jstr;
}
#endif // MINGW_LIBGCJ_UNICODE
_Jv_Win32TempString::_Jv_Win32TempString(jstring jstr):
buf_(0)
{
if (jstr == 0)
return;
#ifdef MINGW_LIBGCJ_UNICODE
int len = jstr->length();
#else
int len = unicodeToNative(jstr);
#endif // MINGW_LIBGCJ_UNICODE
int bytesNeeded = (len + 1) * sizeof(TCHAR);
if (bytesNeeded <= (int) sizeof(stackbuf_))
buf_ = stackbuf_;
else
buf_ = (LPTSTR) _Jv_Malloc(bytesNeeded);
#ifdef MINGW_LIBGCJ_UNICODE
_tcsncpy(buf_, (LPCTSTR) JvGetStringChars (jstr), len);
#else
unicodeToNative(jstr, buf_, len);
#endif // MINGW_LIBGCJ_UNICODE
buf_[len] = 0;
}
_Jv_Win32TempString::~_Jv_Win32TempString()
{
if (buf_ && buf_ != stackbuf_)
_Jv_Free (buf_);
}
WSAEventWrapper::WSAEventWrapper ():
m_hEvent(0),
m_fd(0),
m_dwSelFlags(0)
{}
WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags):
m_hEvent(0),
m_fd(0),
m_dwSelFlags(0)
{
init(fd, dwSelFlags);
}
void WSAEventWrapper::init(int fd, DWORD dwSelFlags)
{
m_fd = fd;
m_dwSelFlags = dwSelFlags;
m_hEvent = WSACreateEvent ();
if (dwSelFlags)
WSAEventSelect(fd, m_hEvent, dwSelFlags);
}
WSAEventWrapper::~WSAEventWrapper ()
{
if (m_dwSelFlags)
{
WSAEventSelect(m_fd, m_hEvent, 0);
if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT))
{
unsigned long lSockOpt = 0L;
::ioctlsocket (m_fd, FIONBIO, &lSockOpt);
}
}
WSACloseEvent (m_hEvent);
}
jstring
_Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode)
{
LPTSTR lpMsgBuf = 0;
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS;
FormatMessage (dwFlags,
NULL,
(DWORD) nErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL);
jstring ret;
if (lpszPrologue)
{
LPTSTR lpszTemp =
(LPTSTR) _Jv_Malloc ((_tcslen (lpszPrologue) +
_tcslen (lpMsgBuf) + 3) * sizeof(TCHAR) );
_tcscpy (lpszTemp, lpszPrologue);
_tcscat (lpszTemp, _T(": "));
_tcscat (lpszTemp, lpMsgBuf);
ret = _Jv_Win32NewString (lpszTemp);
_Jv_Free (lpszTemp);
}
else
{
ret = _Jv_Win32NewString (lpMsgBuf);
}
LocalFree(lpMsgBuf);
return ret;
}
jstring
_Jv_WinStrError (int nErrorCode)
{
return _Jv_WinStrError (0, nErrorCode);
}
void _Jv_ThrowIOException (DWORD dwErrorCode)
{
throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
}
void _Jv_ThrowIOException()
{
DWORD dwErrorCode = WSAGetLastError ();
_Jv_ThrowIOException (dwErrorCode);
}
void _Jv_ThrowSocketException (DWORD dwErrorCode)
{
throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode));
}
void _Jv_ThrowSocketException()
{
DWORD dwErrorCode = WSAGetLastError ();
_Jv_ThrowSocketException (dwErrorCode);
}
void
_Jv_platform_initialize (void)
{
WSADATA data;
if (WSAStartup (MAKEWORD (2, 2), &data))
MessageBox (NULL, _T("Error initialising winsock library."), _T("Error"),
MB_OK | MB_ICONEXCLAMATION);
SetUnhandledExceptionFilter (win32_exception_handler);
GetModuleFileNameA(NULL, exec_name, sizeof(exec_name));
}
jlong
_Jv_platform_gettimeofday ()
{
struct timeb t;
ftime (&t);
return t.time * 1000LL + t.millitm;
}
int _CRT_MT = 1;
extern "C" int
__mingwthr_key_dtor (DWORD, void (*) (void *))
{
return 0;
}
static bool dirExists (LPCTSTR dir)
{
DWORD dwAttrs = ::GetFileAttributes (dir);
return dwAttrs != 0xFFFFFFFF &&
(dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
static void getUserHome(LPTSTR userHome, LPCTSTR userId)
{
LPTSTR uh = _tgetenv (_T("USERPROFILE"));
if (uh)
{
_tcscpy(userHome, uh);
}
else
{
TCHAR userHomePath[MAX_PATH], winHome[MAX_PATH];
::GetWindowsDirectory(winHome, MAX_PATH);
_stprintf(userHomePath, _T("%s\\Profiles\\%s"), winHome, userId);
if (dirExists (userHomePath))
_tcscpy(userHome, userHomePath);
else
_tcscpy(userHome, winHome);
}
}
void
_Jv_platform_initProperties (java::util::Properties* newprops)
{
#define SET(Prop,Val) \
newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
SET ("file.separator", _T("\\"));
SET ("path.separator", _T(";"));
SET ("line.separator", _T("\r\n"));
DWORD buflen = MAX_PATH;
TCHAR buffer[buflen];
if (buffer != NULL)
{
if (GetCurrentDirectory (buflen, buffer))
SET ("user.dir", buffer);
if (GetTempPath (buflen, buffer))
SET ("java.io.tmpdir", buffer);
}
buflen = 257; TCHAR userName[buflen];
if (GetUserName (userName, &buflen))
SET ("user.name", userName);
TCHAR userHome[MAX_PATH];
getUserHome(userHome, userName);
SET ("user.home", userHome);
OSVERSIONINFO osvi;
ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx (&osvi))
{
if (buffer != NULL)
{
_stprintf (buffer, _T("%d.%d"), (int) osvi.dwMajorVersion,
(int) osvi.dwMinorVersion);
SET ("os.version", buffer);
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
SET ("os.name", _T("Windows 95"));
else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
SET ("os.name", _T("Windows 98"));
else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
SET ("os.name", _T("Windows Me"));
else
SET ("os.name", _T("Windows ??"));
break;
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion <= 4 )
SET ("os.name", _T("Windows NT"));
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
SET ("os.name", _T("Windows 2000"));
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
SET ("os.name", _T("Windows XP"));
else
SET ("os.name", _T("Windows NT ??"));
break;
default:
SET ("os.name", _T("Windows UNKNOWN"));
break;
}
}
SYSTEM_INFO si;
GetSystemInfo (&si);
switch (si.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
SET ("os.arch", _T("x86"));
break;
case PROCESSOR_ARCHITECTURE_MIPS:
SET ("os.arch", _T("mips"));
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
SET ("os.arch", _T("alpha"));
break;
case PROCESSOR_ARCHITECTURE_PPC:
SET ("os.arch", _T("ppc"));
break;
case PROCESSOR_ARCHITECTURE_IA64:
SET ("os.arch", _T("ia64"));
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
SET ("os.arch", _T("unknown"));
break;
}
}
int
backtrace (void **__array, int __size)
{
register void *_ebp __asm__ ("ebp");
register void *_esp __asm__ ("esp");
unsigned int *rfp;
int i=0;
for (rfp = *(unsigned int**)_ebp;
rfp && i < __size;
rfp = *(unsigned int **)rfp)
{
int diff = *rfp - (unsigned int)rfp;
if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
__array[i++] = (void*)(rfp[1]-4);
}
return i;
}
int
_Jv_pipe (int filedes[2])
{
return _pipe (filedes, 4096, _O_BINARY);
}
void
_Jv_platform_close_on_exec (HANDLE h)
{
SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
}