OSDN Git Service

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