aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sysdep.c
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2009-04-20 10:26:13 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2009-04-20 10:26:13 +0200
commit3f25c54d814c705750dc1535dd935b39afc7b779 (patch)
treebd81a0aab892d56ae076ec2454b8fbf55ef392a2 /gcc/ada/sysdep.c
parent8dbf3473b19d7579acb40e4f0342d4a1c055e4d5 (diff)
downloadgcc-3f25c54d814c705750dc1535dd935b39afc7b779.zip
gcc-3f25c54d814c705750dc1535dd935b39afc7b779.tar.gz
gcc-3f25c54d814c705750dc1535dd935b39afc7b779.tar.bz2
[multiple changes]
2009-04-20 Hristian Kirtchev <kirtchev@adacore.com> * a-calend.adb: Remove types char_Pointer, int, tm and tm_Pointer. (localtime_tzoff): This routine no longer accepts an actual of type tm_Pointer. (UTC_Time_Offset): Remove local variable Secs_TM. * sysdep.c (__gnat_localtime_tzoff): This routine no longer accepts an actual of type struct tm*. Add local variable of type struct tm for all targets that provide localtime_r and need to invoke it. 2009-04-20 Thomas Quinot <quinot@adacore.com> * s-oscons-tmplt.c, g-socket.adb, g-socket.ads (GNAT.Sockets.Resolve_Error): Add case of EPIPE Add case of EAGAIN for platforms where it is not equal to EWOULDBLOCK From-SVN: r146369
Diffstat (limited to 'gcc/ada/sysdep.c')
-rw-r--r--gcc/ada/sysdep.c99
1 files changed, 58 insertions, 41 deletions
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 56f3ebd..8a227b4 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -743,26 +743,53 @@ extern void (*Unlock_Task) (void);
/* Reentrant localtime for Windows and OS/2. */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+static const unsigned long long w32_epoch_offset = 11644473600ULL;
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
- DWORD dwRet;
- struct tm *tmp;
+ union
+ {
+ FILETIME ft_time;
+ unsigned long long ull_time;
+ } utc_time, local_time;
+
+ SYSTEMTIME utc_sys_time, local_sys_time;
TIME_ZONE_INFORMATION tzi;
+ BOOL status = 1;
+ DWORD tzi_status;
+
(*Lock_Task) ();
- tmp = localtime (timer);
- memcpy (tp, tmp, sizeof (struct tm));
- dwRet = GetTimeZoneInformation (&tzi);
- *off = tzi.Bias;
- if (tp->tm_isdst > 0)
- *off = *off + tzi.DaylightBias;
- *off = *off * -60;
+
+ /* First convert unix time_t structure to windows FILETIME format. */
+ utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
+ * 10000000ULL;
+
+ tzi_status = GetTimeZoneInformation (&tzi);
+
+ /* If GetTimeZoneInformation does not return a value between 0 and 2 then
+ it means that we were not able to retrieve timezone informations.
+ Note that we cannot use here FileTimeToLocalFileTime as Windows will use
+ in always in this case the current timezone setting. As suggested on
+ MSDN we use the following three system calls to get the right information.
+ Note also that starting with Windows Vista new functions are provided to
+ get timezone settings that depend on the year. We cannot use them as we
+ still support Windows XP and Windows 2003. */
+ status = (tzi_status >= 0 && tzi_status <= 2)
+ && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
+ && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
+ && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
+
+ if (!status)
+ /* An error occurs so return invalid_tzoff. */
+ *off = __gnat_invalid_tzoff;
+ else
+ *off = (long) ((local_time.ull_time - utc_time.ull_time) / 10000000ULL);
+
(*Unlock_Task) ();
- return tp;
}
#else
@@ -774,16 +801,14 @@ __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
the Lynx convention when building against the legacy API. */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
/* Treat all time values in GMT */
- localtime_r (tp, timer);
*off = 0;
- return NULL;
}
#else
@@ -795,28 +820,21 @@ __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
/* All other targets provide a standard localtime_r */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
- localtime_r (timer, tp);
+ struct tm tp;
+ localtime_r (timer, &tp);
/* AIX, HPUX, SGI Irix, Sun Solaris */
#if defined (_AIX) || defined (__hpux__) || defined (sgi) || defined (sun)
- /* The contents of external variable "timezone" may not always be
- initialized. Instead of returning an incorrect offset, treat the local
- time zone as 0 (UTC). The value of 28 hours is the maximum valid offset
- allowed by Ada.Calendar.Time_Zones. */
- if ((timezone < -28 * 3600) || (timezone > 28 * 3600))
- *off = 0;
- else
- {
- *off = (long) -timezone;
- if (tp->tm_isdst > 0)
- *off = *off + 3600;
- }
+ *off = (long) -timezone;
+ if (tp.tm_isdst > 0)
+ *off = *off + 3600;
+
/* Lynx - Treat all time values in GMT */
#elif defined (__Lynx__)
*off = 0;
@@ -850,17 +868,16 @@ __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
}
}
-/* Darwin, Free BSD, Linux, Tru64, where there exists a component tm_gmtoff
- in struct tm */
+/* Darwin, Free BSD, Linux, Tru64, where component tm_gmtoff is present in
+ struct tm */
#elif defined (__APPLE__) || defined (__FreeBSD__) || defined (linux) ||\
(defined (__alpha__) && defined (__osf__)) || defined (__GLIBC__)
- *off = tp->tm_gmtoff;
+ *off = tp.tm_gmtoff;
/* All other platforms: Treat all time values in GMT */
#else
*off = 0;
#endif
- return NULL;
}
#endif