OSDN Git Service

* doc/extend.texi: Mention H8S wherever H8/300H is mentioned.
[pf3gnuchains/gcc-fork.git] / libjava / win32.cc
1 // win32.cc - Helper functions for Microsoft-flavored OSs.
2
3 /* Copyright (C) 2002, 2003  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12 #include <platform.h>
13 #include <sys/timeb.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16
17 #include <java/lang/ArithmeticException.h>
18 #include <java/lang/UnsupportedOperationException.h>
19 #include <java/io/IOException.h>
20 #include <java/net/SocketException.h>
21 #include <java/util/Properties.h>
22
23 static LONG CALLBACK
24 win32_exception_handler (LPEXCEPTION_POINTERS e)
25 {
26   if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
27     _Jv_ThrowNullPointerException();
28   else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
29     throw new java::lang::ArithmeticException;
30   else
31     return EXCEPTION_CONTINUE_SEARCH;
32 }
33
34 // Platform-specific executable name
35 static char exec_name[MAX_PATH];
36   // initialized in _Jv_platform_initialize()
37
38 const char *_Jv_ThisExecutable (void)
39 {
40   return exec_name;
41 }
42
43 // Helper classes and methods implementation
44   
45 // class WSAEventWrapper
46 WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags):
47   m_hEvent(0),
48   m_fd(fd),
49   m_dwSelFlags(dwSelFlags)
50 {
51   m_hEvent = WSACreateEvent ();
52   if (dwSelFlags)
53     WSAEventSelect(fd, m_hEvent, dwSelFlags);
54 }
55
56 WSAEventWrapper::~WSAEventWrapper ()
57 {
58   if (m_dwSelFlags)
59   {
60     WSAEventSelect(m_fd, m_hEvent, 0);
61     if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT))
62     {
63       // Set the socket back to non-blocking mode.
64       // Ignore any error since we're in a destructor.
65       unsigned long lSockOpt = 0L;
66         // blocking mode
67       ::ioctlsocket (m_fd, FIONBIO, &lSockOpt);
68     }
69   }
70   WSACloseEvent (m_hEvent);
71 }
72
73 // Error string text.
74 jstring
75 _Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode)
76 {
77   LPTSTR lpMsgBuf = 0;
78
79   DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
80     FORMAT_MESSAGE_FROM_SYSTEM |
81     FORMAT_MESSAGE_IGNORE_INSERTS;
82
83   FormatMessage (dwFlags,
84     NULL,
85     (DWORD) nErrorCode,
86     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
87     (LPTSTR) &lpMsgBuf,
88     0,
89     NULL);
90
91   jstring ret;
92   if (lpszPrologue)
93     {
94       LPTSTR lpszTemp =
95         (LPTSTR) _Jv_Malloc (strlen (lpszPrologue) +
96           strlen (lpMsgBuf) + 3);
97       strcpy (lpszTemp, lpszPrologue);
98       strcat (lpszTemp, ": ");
99       strcat (lpszTemp, lpMsgBuf);
100       ret = JvNewStringLatin1 (lpszTemp);
101     } 
102   else
103     {
104       ret = JvNewStringLatin1 (lpMsgBuf);
105     }
106
107   LocalFree(lpMsgBuf);
108   return ret;
109 }
110
111 jstring
112 _Jv_WinStrError (int nErrorCode)
113 {
114   return _Jv_WinStrError (0, nErrorCode);
115 }
116
117 void _Jv_ThrowIOException (DWORD dwErrorCode)
118 {
119   throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
120 }
121
122 void _Jv_ThrowIOException()
123 {
124   DWORD dwErrorCode = WSAGetLastError ();
125   _Jv_ThrowIOException (dwErrorCode);
126 }
127
128 void _Jv_ThrowSocketException (DWORD dwErrorCode)
129 {
130   throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode));
131 }
132
133 void _Jv_ThrowSocketException()
134 {
135   DWORD dwErrorCode = WSAGetLastError ();
136   _Jv_ThrowSocketException (dwErrorCode);
137 }
138
139 // Platform-specific VM initialization.
140 void
141 _Jv_platform_initialize (void)
142 {
143   // Initialise winsock for networking
144   WSADATA data;
145   if (WSAStartup (MAKEWORD (1, 1), &data))
146     MessageBox (NULL, "Error initialising winsock library.", "Error",
147     MB_OK | MB_ICONEXCLAMATION);
148
149   // Install exception handler
150   SetUnhandledExceptionFilter (win32_exception_handler);
151
152   // Initialize our executable name
153   GetModuleFileName(NULL, exec_name, sizeof(exec_name));
154 }
155
156 // gettimeofday implementation.
157 jlong
158 _Jv_platform_gettimeofday ()
159 {
160   struct timeb t;
161   ftime (&t);
162   return t.time * 1000LL + t.millitm;
163 }
164
165 // The following definitions "fake out" mingw to think that -mthreads
166 // was enabled and that mingwthr.dll was linked. GCJ-compiled
167 // applications don't need this helper library because we can safely
168 // detect thread death (return from Thread.run()).
169
170 int _CRT_MT = 1;
171
172 extern "C" int
173 __mingwthr_key_dtor (DWORD, void (*) (void *))
174 {
175   // FIXME: for now we do nothing; this causes a memory leak of
176   //        approximately 24 bytes per thread created.
177   return 0;
178 }
179
180 // Set platform-specific System properties.
181 void
182 _Jv_platform_initProperties (java::util::Properties* newprops)
183 {
184   // A convenience define.
185 #define SET(Prop,Val) \
186   newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
187
188   SET ("file.separator", "\\");
189   SET ("path.separator", ";");
190   SET ("line.separator", "\r\n");
191
192   // Use GetCurrentDirectory to set 'user.dir'.
193   DWORD buflen = MAX_PATH;
194   char *buffer = (char *) _Jv_MallocUnchecked (buflen);
195   if (buffer != NULL)
196     {
197       if (GetCurrentDirectory (buflen, buffer))
198   SET ("user.dir", buffer);
199
200       if (GetTempPath (buflen, buffer))
201   SET ("java.io.tmpdir", buffer);
202
203       _Jv_Free (buffer);
204     }
205
206   // Use GetUserName to set 'user.name'.
207   buflen = 257;  // UNLEN + 1
208   buffer = (char *) _Jv_MallocUnchecked (buflen);
209   if (buffer != NULL)
210     {
211       if (GetUserName (buffer, &buflen))
212         SET ("user.name", buffer);
213       _Jv_Free (buffer);
214     }
215
216   // According to the api documentation for 'GetWindowsDirectory()', the
217   // environmental variable HOMEPATH always specifies the user's home
218   // directory or a default directory.  On the 3 windows machines I checked
219   // only 1 had it set.  If it's not set, JDK1.3.1 seems to set it to
220   // the windows directory, so we'll do the same.
221   char *userHome = NULL;
222   if ((userHome = ::getenv ("HOMEPATH")) == NULL )
223     {
224       // Check HOME since it's what I use.
225       if ((userHome = ::getenv ("HOME")) == NULL )
226         {
227           // Not found - use the windows directory like JDK1.3.1 does.
228           char *winHome = (char *) _Jv_MallocUnchecked (MAX_PATH);
229           if (winHome != NULL)
230             {
231               if (GetWindowsDirectory (winHome, MAX_PATH))
232         SET ("user.home", winHome);
233               _Jv_Free (winHome);
234             }
235         }
236      }
237   if (userHome != NULL)
238     SET ("user.home", userHome);
239
240   // Get and set some OS info.
241   OSVERSIONINFO osvi;
242   ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
243   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
244   if (GetVersionEx (&osvi))
245     {
246       char *buffer = (char *) _Jv_MallocUnchecked (30);
247       if (buffer != NULL)
248         {
249           sprintf (buffer, "%d.%d", (int) osvi.dwMajorVersion,
250            (int) osvi.dwMinorVersion);
251           SET ("os.version", buffer);
252           _Jv_Free (buffer);
253         }
254
255       switch (osvi.dwPlatformId)
256         {
257           case VER_PLATFORM_WIN32_WINDOWS:
258             if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
259               SET ("os.name", "Windows 95");
260             else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
261               SET ("os.name", "Windows 98");
262             else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
263               SET ("os.name", "Windows Me");
264             else
265               SET ("os.name", "Windows ??");
266             break;
267
268           case VER_PLATFORM_WIN32_NT:
269             if (osvi.dwMajorVersion <= 4 )
270               SET ("os.name", "Windows NT");
271             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
272               SET ("os.name", "Windows 2000");
273             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
274               SET ("os.name", "Windows XP");
275             else
276               SET ("os.name", "Windows NT ??");
277             break;
278
279           default:
280             SET ("os.name", "Windows UNKNOWN");
281             break;
282        }
283   }
284
285   // Set the OS architecture.
286   SYSTEM_INFO si;
287   GetSystemInfo (&si);
288   switch (si.wProcessorArchitecture)
289     {
290       case PROCESSOR_ARCHITECTURE_INTEL:
291         SET ("os.arch", "x86");
292         break;
293       case PROCESSOR_ARCHITECTURE_MIPS:
294         SET ("os.arch", "mips");
295         break;
296       case PROCESSOR_ARCHITECTURE_ALPHA:
297         SET ("os.arch", "alpha");
298         break;
299       case PROCESSOR_ARCHITECTURE_PPC:  
300         SET ("os.arch", "ppc");
301         break;
302       case PROCESSOR_ARCHITECTURE_IA64:
303         SET ("os.arch", "ia64");
304         break;
305       case PROCESSOR_ARCHITECTURE_UNKNOWN:
306       default:
307         SET ("os.arch", "unknown");
308         break;
309     }
310 }
311
312 /* Store up to SIZE return address of the current program state in
313    ARRAY and return the exact number of values stored.  */
314 int
315 backtrace (void **__array, int __size)
316 {
317   register void *_ebp __asm__ ("ebp");
318   register void *_esp __asm__ ("esp");
319   unsigned int *rfp;
320
321   int i=0;
322   for (rfp = *(unsigned int**)_ebp;
323        rfp && i < __size;
324        rfp = *(unsigned int **)rfp)
325     {
326       int diff = *rfp - (unsigned int)rfp;
327       if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
328
329     __array[i++] = (void*)(rfp[1]-4);
330   }
331   return i;
332 }
333
334 int
335 _Jv_select (int n, fd_set *readfds, fd_set  *writefds,
336       fd_set *exceptfds, struct timeval *timeout)
337 {
338   int r = ::select (n, readfds, writefds, exceptfds, timeout);
339   if (r == SOCKET_ERROR)
340     {
341       DWORD dwErrorCode = WSAGetLastError ();
342       throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
343     }
344   return r;      
345 }
346
347 int
348 _Jv_pipe (int filedes[2])
349 {
350   return _pipe (filedes, 4096, _O_BINARY);
351 }