OSDN Git Service

* gcc.texi: Use terms "GNU Compiler Collection" and "GCC".
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natSystem.cc
1 // natSystem.cc - Native code implementing System class.
2
3 /* Copyright (C) 1998, 1999  Cygnus Solutions
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
13 #ifdef HAVE_GETPWUID_R
14 #define _POSIX_PTHREAD_SEMANTICS
15 #ifndef _REENTRANT
16 #define _REENTRANT
17 #endif
18 #endif
19
20 #include <string.h>
21 #include <time.h>
22 #include <stdlib.h>
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif
31
32 #ifdef HAVE_PWD_H
33 #include <pwd.h>
34 #endif
35 #include <errno.h>
36
37 #ifdef HAVE_UNAME
38 #include <sys/utsname.h>
39 #endif
40
41 #include <cni.h>
42 #include <jvm.h>
43 #include <java/lang/System.h>
44 #include <java/lang/Class.h>
45 #include <java/lang/ArrayStoreException.h>
46 #include <java/lang/ArrayIndexOutOfBoundsException.h>
47 #include <java/lang/NullPointerException.h>
48 #include <java/util/Properties.h>
49 #include <java/io/PrintStream.h>
50 #include <java/io/InputStream.h>
51
52 #define SystemClass _CL_Q34java4lang6System
53 extern java::lang::Class SystemClass;
54
55 \f
56
57 #if defined (ECOS)
58 extern "C" unsigned long long _clock (void);
59 #endif
60
61 void
62 java::lang::System::setErr (java::io::PrintStream *newErr)
63 {
64   checkSetIO ();
65   // This violates `final' semantics.  Oh well.
66   err = newErr;
67 }
68
69 void
70 java::lang::System::setIn (java::io::InputStream *newIn)
71 {
72   checkSetIO ();
73   // This violates `final' semantics.  Oh well.
74   in = newIn;
75 }
76
77 void
78 java::lang::System::setOut (java::io::PrintStream *newOut)
79 {
80   checkSetIO ();
81   // This violates `final' semantics.  Oh well.
82   out = newOut;
83 }
84
85 void
86 java::lang::System::arraycopy (jobject src, jint src_offset,
87                                jobject dst, jint dst_offset,
88                                jint count)
89 {
90   if (! src || ! dst)
91     _Jv_Throw (new NullPointerException);
92
93   jclass src_c = src->getClass();
94   jclass dst_c = dst->getClass();
95   jclass src_comp = src_c->getComponentType();
96   jclass dst_comp = dst_c->getComponentType();
97
98   if (! src_c->isArray() || ! dst_c->isArray()
99       || src_comp->isPrimitive() != dst_comp->isPrimitive()
100       || (src_comp->isPrimitive() && src_comp != dst_comp))
101     _Jv_Throw (new ArrayStoreException);
102
103   __JArray *src_a = (__JArray *) src;
104   __JArray *dst_a = (__JArray *) dst;
105   if (src_offset < 0 || dst_offset < 0 || count < 0
106       || src_offset + count > src_a->length
107       || dst_offset + count > dst_a->length)
108     _Jv_Throw (new ArrayIndexOutOfBoundsException);
109
110   // Do-nothing cases.
111   if ((src == dst && src_offset == dst_offset)
112       || ! count)
113     return;
114
115   // If both are primitive, we can optimize trivially.  If DST
116   // components are always assignable from SRC components, then we
117   // will never need to raise an error, and thus can do the
118   // optimization.  If source and destinations are the same, then we
119   // know that the assignability premise always holds.
120   const bool prim = src_comp->isPrimitive();
121   if (prim || dst_comp->isAssignableFrom(src_comp) || src == dst)
122     {
123       const size_t size = (prim ? src_comp->size()
124                            : sizeof elements((jobjectArray)src)[0]);
125
126       // In an ideal world we would do this via a virtual function in
127       // __JArray.  However, we can't have virtual functions in
128       // __JArray due to the need to copy an array's virtual table in
129       // _Jv_FindArrayClass.
130       // We can't just pick a single subtype of __JArray to use due to
131       // alignment concerns.
132       char *src_elts = NULL;
133       if (! prim)
134         src_elts = (char *) elements ((jobjectArray) src);
135       else if (src_comp == JvPrimClass (byte))
136         src_elts = (char *) elements ((jbyteArray) src);
137       else if (src_comp == JvPrimClass (short))
138         src_elts = (char *) elements ((jshortArray) src);
139       else if (src_comp == JvPrimClass (int))
140         src_elts = (char *) elements ((jintArray) src);
141       else if (src_comp == JvPrimClass (long))
142         src_elts = (char *) elements ((jlongArray) src);
143       else if (src_comp == JvPrimClass (boolean))
144         src_elts = (char *) elements ((jbooleanArray) src);
145       else if (src_comp == JvPrimClass (char))
146         src_elts = (char *) elements ((jcharArray) src);
147       else if (src_comp == JvPrimClass (float))
148         src_elts = (char *) elements ((jfloatArray) src);
149       else if (src_comp == JvPrimClass (double))
150         src_elts = (char *) elements ((jdoubleArray) src);
151       src_elts += size * src_offset;
152
153       char *dst_elts = NULL;
154       if (! prim)
155         dst_elts = (char *) elements ((jobjectArray) dst);
156       else if (dst_comp == JvPrimClass (byte))
157         dst_elts = (char *) elements ((jbyteArray) dst);
158       else if (dst_comp == JvPrimClass (short))
159         dst_elts = (char *) elements ((jshortArray) dst);
160       else if (dst_comp == JvPrimClass (int))
161         dst_elts = (char *) elements ((jintArray) dst);
162       else if (dst_comp == JvPrimClass (long))
163         dst_elts = (char *) elements ((jlongArray) dst);
164       else if (dst_comp == JvPrimClass (boolean))
165         dst_elts = (char *) elements ((jbooleanArray) dst);
166       else if (dst_comp == JvPrimClass (char))
167         dst_elts = (char *) elements ((jcharArray) dst);
168       else if (dst_comp == JvPrimClass (float))
169         dst_elts = (char *) elements ((jfloatArray) dst);
170       else if (dst_comp == JvPrimClass (double))
171         dst_elts = (char *) elements ((jdoubleArray) dst);
172       dst_elts += size * dst_offset;
173
174       // We don't bother trying memcpy.  It can't be worth the cost of
175       // the check.
176       memmove ((void *) dst_elts, (void *) src_elts, count * size);
177     }
178   else
179     {
180       jobject *src_elts = elements ((jobjectArray) src_a) + src_offset;
181       jobject *dst_elts = elements ((jobjectArray) dst_a) + dst_offset;
182
183       for (int i = 0; i < count; ++i)
184         {
185           if (*src_elts
186               && ! dst_comp->isAssignableFrom((*src_elts)->getClass()))
187             _Jv_Throw (new ArrayStoreException);
188           *dst_elts++ = *src_elts++;
189         }
190     }
191 }
192
193 jlong
194 java::lang::System::currentTimeMillis (void)
195 {
196   jlong r;
197
198 #if defined (HAVE_GETTIMEOFDAY)
199   struct timeval tv;
200   gettimeofday (&tv, NULL);
201   r = (jlong) tv.tv_sec * 1000 + tv.tv_usec / 1000;
202 #elif defined (HAVE_TIME)
203   r = time (NULL) * 1000;
204 #elif defined (HAVE_FTIME)
205   struct timeb t;
206   ftime (&t);
207   r = t.time * 1000 + t.millitm;
208 #elif defined (ECOS)
209   r = _clock();
210 #else
211   // In the absence of any function, time remains forever fixed.
212   r = 23;
213 #endif
214
215   return r;
216 }
217
218 jint
219 java::lang::System::identityHashCode (jobject obj)
220 {
221   return _Jv_HashCode (obj);
222 }
223
224 #ifndef DEFAULT_FILE_ENCODING
225 #define DEFAULT_FILE_ENCODING "8859_1"
226 #endif
227 static char *default_file_encoding = DEFAULT_FILE_ENCODING;
228
229 void
230 java::lang::System::init_properties (void)
231 {
232   {
233     // We only need to synchronize around this gatekeeper.
234     JvSynchronize sync (&SystemClass);
235     if (prop_init)
236       return;
237     prop_init = true;
238   }
239
240   properties = new java::util::Properties ();
241   // A convenience define.
242 #define SET(Prop,Val) \
243         properties->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
244   SET ("java.version", VERSION);
245   SET ("java.vendor", "Cygnus Solutions");
246   SET ("java.vendor.url", "http://sourceware.cygnus.com/java/");
247   SET ("java.class.version", GCJVERSION);
248   // FIXME: how to set these given location-independence?
249   // SET ("java.home", "FIXME");
250   // SET ("java.class.path", "FIXME");
251   SET ("file.encoding", default_file_encoding);
252
253 #ifdef WIN32
254   SET ("file.separator", "\\");
255   SET ("path.separator", ";");
256   SET ("line.separator", "\r\n");
257 #else
258   // Unix.
259   SET ("file.separator", "/");
260   SET ("path.separator", ":");
261   SET ("line.separator", "\n");
262 #endif
263
264 #ifdef HAVE_UNAME
265   struct utsname u;
266   if (! uname (&u))
267     {
268       SET ("os.name", u.sysname);
269       SET ("os.arch", u.machine);
270       SET ("os.version", u.release);
271     }
272   else
273     {
274       SET ("os.name", "unknown");
275       SET ("os.arch", "unknown");
276       SET ("os.version", "unknown");
277     }
278 #endif /* HAVE_UNAME */
279
280 #ifdef HAVE_PWD_H
281   uid_t user_id = getuid ();
282   struct passwd *pwd_entry;
283
284 #ifdef HAVE_GETPWUID_R
285   struct passwd pwd_r;
286   size_t len_r = 200;
287   char *buf_r = (char *) _Jv_AllocBytes (len_r);
288
289   while (buf_r != NULL)
290     {
291       int r = getpwuid_r (user_id, &pwd_r, buf_r, len_r, &pwd_entry);
292       if (r == 0)
293         break;
294       else if (r != ERANGE)
295         {
296           pwd_entry = NULL;
297           break;
298         }
299       len_r *= 2;
300       buf_r = (char *) _Jv_AllocBytes (len_r);
301     }
302 #else
303   pwd_entry = getpwuid (user_id);
304 #endif /* HAVE_GETPWUID_R */
305
306   if (pwd_entry != NULL)
307     {
308       SET ("user.name", pwd_entry->pw_name);
309       SET ("user.home", pwd_entry->pw_dir);
310     }
311 #endif /* HAVE_PWD_H */
312
313 #ifdef HAVE_UNISTD_H
314   /* Use getcwd to set "user.dir". */
315   int buflen = 250;
316   char *buffer = (char *) malloc (buflen);
317   while (buffer != NULL)
318     {
319       if (getcwd (buffer, buflen) != NULL)
320         {
321           SET ("user.dir", buffer);
322           break;
323         }
324       if (errno != ERANGE)
325         break;
326       buflen = 2 * buflen;
327       buffer = (char *) realloc (buffer, buflen);
328     }
329   if (buffer != NULL)
330     free (buffer);
331 #endif
332 }