summaryrefslogtreecommitdiff
path: root/native/jni/java-util/java_util_VMTimeZone.c
diff options
context:
space:
mode:
authorRoman Kennke <roman@kennke.org>2006-01-25 10:40:12 +0000
committerRoman Kennke <roman@kennke.org>2006-01-25 10:40:12 +0000
commitc2b071e804b01db01ffe55228c7f00ddc1babc1b (patch)
tree177e5850ca07b58a3a92f2694233c8b9590e0200 /native/jni/java-util/java_util_VMTimeZone.c
parent7854af476c09cbf8655deb5d8eed545fee3f1b4b (diff)
downloadclasspath-c2b071e804b01db01ffe55228c7f00ddc1babc1b.tar.gz
2006-01-25 Roman Kennke <kennke@aicas.com>
* configure.ac * native/Makefile.am * native/jni/classpath/Makefile.am * native/jni/classpath/jcl.c * native/jni/classpath/jcl.h * native/jni/classpath/native_state.c * native/jni/gtk-peer/Makefile.am * native/jni/java-io/Makefile.am * native/jni/java-io/java_io_VMFile.c * native/jni/java-io/java_io_VMObjectStreamClass.c * native/jni/java-lang/Makefile.am * native/jni/java-net/Makefile.am * native/jni/java-net/java_net_VMInetAddress.c * native/jni/java-net/javanet.c * native/jni/java-net/javanet.h * native/jni/java-nio/Makefile.am * native/jni/java-nio/gnu_java_nio_VMPipe.c * native/jni/java-nio/gnu_java_nio_VMSelector.c * native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c * native/jni/java-nio/java_nio_MappedByteBufferImpl.c * native/jni/java-nio/java_nio_VMDirectByteBuffer.c * native/jni/java-util/Makefile.am * native/jni/java-util/java_util_VMTimeZone.c * native/jni/midi-dssi/Makefile.am * native/jni/xmlj/Makefile.am * native/target/Makefile.am * native/target/Linux/target_native_math.h * native/target/Linux/target_native_memory.h * native/target/Linux/Makefile.am * native/target/Linux/target_native_io.h * native/target/Linux/target_native_math_float.h * native/target/Linux/target_native_math_int.h * native/target/generic/target_generic.c * native/target/generic/target_generic_io.c * native/target/generic/target_generic_math.h * native/target/generic/target_generic_memory.h * native/target/generic/target_generic_misc.c * native/target/generic/target_generic_network.c * native/target/generic/Makefile.am * native/target/generic/target_generic.h * native/target/generic/target_generic_file.h * native/target/generic/target_generic_io.h * native/target/generic/target_generic_math_float.h * native/target/generic/target_generic_math_int.h * native/target/generic/target_generic_misc.h * native/target/generic/target_generic_network.h: Reverted target native related changes back to the state of the 0.20 release. * native/target/MinGW/.cvsignore * native/target/MinGW/Makefile.am * native/target/MinGW/target_native.h * native/target/MinGW/target_native_file.h * native/target/MinGW/target_native_io.h * native/target/MinGW/target_native_math.h * native/target/MinGW/target_native_memory.h * native/target/MinGW/target_native_misc.h * native/target/MinGW/target_native_network.h * native/target/RTEMS/.cvsignore * native/target/RTEMS/Makefile.am * native/target/RTEMS/target_native.h * native/target/RTEMS/target_native_file.h * native/target/RTEMS/target_native_io.h * native/target/RTEMS/target_native_math.h * native/target/RTEMS/target_native_memory.h * native/target/RTEMS/target_native_misc.h * native/target/RTEMS/target_native_network.h * native/target/SunOS/.cvsignore * native/target/SunOS/Makefile.am * native/target/SunOS/target_native.h * native/target/SunOS/target_native_file.h * native/target/SunOS/target_native_io.h * native/target/SunOS/target_native_math.h * native/target/SunOS/target_native_memory.h * native/target/SunOS/target_native_misc.h * native/target/SunOS/target_native_network.h * native/target/embOS/.cvsignore * native/target/embOS/Makefile.am * native/target/embOS/target_native.h * native/target/embOS/target_native_file.h * native/target/embOS/target_native_io.c * native/target/embOS/target_native_io.h * native/target/embOS/target_native_math.h * native/target/embOS/target_native_memory.h * native/target/embOS/target_native_misc.h * native/target/embOS/target_native_network.h * native/target/posix/.cvsignore * native/target/posix/Makefile.am * native/target/posix/target_posix.c * native/target/posix/target_posix.h * native/target/posix/target_posix_file.c * native/target/posix/target_posix_file.h * native/target/posix/target_posix_io.c * native/target/posix/target_posix_io.h * native/target/posix/target_posix_math.c * native/target/posix/target_posix_math.h * native/target/posix/target_posix_memory.c * native/target/posix/target_posix_memory.h * native/target/posix/target_posix_misc.c * native/target/posix/target_posix_misc.h * native/target/posix/target_posix_network.c * native/target/posix/target_posix_network.h: Removed.
Diffstat (limited to 'native/jni/java-util/java_util_VMTimeZone.c')
-rw-r--r--native/jni/java-util/java_util_VMTimeZone.c174
1 files changed, 156 insertions, 18 deletions
diff --git a/native/jni/java-util/java_util_VMTimeZone.c b/native/jni/java-util/java_util_VMTimeZone.c
index 111d10b34..a3a986d36 100644
--- a/native/jni/java-util/java_util_VMTimeZone.c
+++ b/native/jni/java-util/java_util_VMTimeZone.c
@@ -37,18 +37,27 @@ exception statement from your version. */
#include "config.h"
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <jcl.h>
#include <jni.h>
-#include "target_native.h"
-#include "target_native_misc.h"
-
#include "java_util_VMTimeZone.h"
+static size_t jint_to_charbuf (char *bufend, jint num);
+
/**
* This method returns a time zone id string which is in the form
* (standard zone name) or (standard zone name)(GMT offset) or
@@ -66,20 +75,149 @@ exception statement from your version. */
* TimeZone object.
*/
JNIEXPORT jstring JNICALL
-Java_java_util_VMTimeZone_getSystemTimeZoneId(JNIEnv *env,
- jclass clazz __attribute__ ((__unused__)))
+Java_java_util_VMTimeZone_getSystemTimeZoneId (JNIEnv * env,
+ jclass clazz
+ __attribute__ ((__unused__)))
{
- char buffer[64]; /* FIXME: large enough? (better not to use malloc(), because of possible failure!) */
- int result;
-
- TARGET_NATIVE_MISC_GET_TIMEZONE_STRING(buffer,sizeof(buffer),result);
- if (result == TARGET_NATIVE_OK)
- {
- return (*env)->NewStringUTF (env, buffer);
- }
- else
- {
- return NULL;
- }
+ struct tm tim;
+#ifndef HAVE_LOCALTIME_R
+ struct tm *lt_tim;
+#endif
+#ifdef HAVE_TM_ZONE
+ int month;
+#endif
+ time_t current_time;
+ long tzoffset;
+ const char *tz1, *tz2;
+ char tzoff[11];
+ size_t tz1_len, tz2_len, tzoff_len;
+ char *tzid;
+ jstring retval;
+
+ time (&current_time);
+#ifdef HAVE_LOCALTIME_R
+ localtime_r (&current_time, &tim);
+#else
+ /* Fall back on non-thread safe localtime. */
+ lt_tim = localtime (&current_time);
+ memcpy (&tim, lt_tim, sizeof (struct tm));
+#endif
+ mktime (&tim);
+
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ /* We will cycle through the months to make sure we hit dst. */
+ month = tim.tm_mon;
+ tz1 = tz2 = NULL;
+ while (tz1 == NULL || tz2 == NULL)
+ {
+ if (tim.tm_isdst > 0)
+ tz2 = tim.tm_zone;
+ else if (tz1 == NULL)
+ {
+ tz1 = tim.tm_zone;
+ month = tim.tm_mon;
+ }
+
+ if (tz1 == NULL || tz2 == NULL)
+ {
+ tim.tm_mon++;
+ tim.tm_mon %= 12;
+ }
+
+ if (tim.tm_mon == month && tz2 == NULL)
+ tz2 = "";
+ else
+ mktime (&tim);
+ }
+ /* We want to make sure the tm struct we use later on is not dst. */
+ tim.tm_mon = month;
+ mktime (&tim);
+#elif defined (HAVE_TZNAME)
+ /* If dst is never used, tzname[1] is the empty string. */
+ tzset ();
+ tz1 = tzname[0];
+ tz2 = tzname[1];
+#else
+ /* Some targets have no concept of timezones. Assume GMT without dst. */
+ tz1 = "GMT";
+ tz2 = "";
+#endif
+
+#ifdef STRUCT_TM_HAS_GMTOFF
+ /* tm_gmtoff is the number of seconds that you must add to GMT to get
+ local time, we need the number of seconds to add to the local time
+ to get GMT. */
+ tzoffset = -1L * tim.tm_gmtoff;
+#elif HAVE_UNDERSCORE_TIMEZONE
+ /* On some systems _timezone is actually defined as time_t. */
+ tzoffset = (long) _timezone;
+#elif HAVE_TIMEZONE
+ /* timezone is secs WEST of UTC. */
+ tzoffset = timezone;
+#else
+ /* FIXME: there must be another global if neither tm_gmtoff nor timezone
+ is available, esp. if tzname is valid.
+ Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
+ calculate between gmtime and localtime (and accounting for possible
+ daylight savings time) as an alternative. */
+ tzoffset = 0L;
+#endif
+
+ if ((tzoffset % 3600) == 0)
+ tzoffset = tzoffset / 3600;
+
+ tz1_len = strlen (tz1);
+ tz2_len = strlen (tz2);
+ tzoff_len = jint_to_charbuf (tzoff + 11, tzoffset);
+ tzid = (char *) malloc (tz1_len + tz2_len + tzoff_len + 1); /* FIXME alloc */
+ memcpy (tzid, tz1, tz1_len);
+ memcpy (tzid + tz1_len, tzoff + 11 - tzoff_len, tzoff_len);
+ memcpy (tzid + tz1_len + tzoff_len, tz2, tz2_len);
+ tzid[tz1_len + tzoff_len + tz2_len] = '\0';
+
+ retval = (*env)->NewStringUTF (env, tzid);
+ free (tzid);
+
+ return retval;
}
+/* Put printed (decimal) representation of NUM in a buffer.
+ BUFEND marks the end of the buffer, which must be at least 11 chars long.
+ Returns the COUNT of chars written. The result is in
+ (BUFEND - COUNT) (inclusive) upto (BUFEND) (exclusive).
+
+ Note that libgcj has a slightly different version called _Jv_FormatInt
+ that works on jchar buffers.
+*/
+
+static size_t
+jint_to_charbuf (char *bufend, jint num)
+{
+ register char *ptr = bufend;
+ jboolean isNeg;
+ if (num < 0)
+ {
+ isNeg = JNI_TRUE;
+ num = -(num);
+ if (num < 0)
+ {
+ /* Must be MIN_VALUE, so handle this special case.
+ FIXME use 'unsigned jint' for num. */
+ *--ptr = '8';
+ num = 214748364;
+ }
+ }
+ else
+ isNeg = JNI_FALSE;
+
+ do
+ {
+ *--ptr = (char) ((int) '0' + (num % 10));
+ num /= 10;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ *--ptr = '-';
+ return bufend - ptr;
+}