diff options
author | Arnaud Charlet <charlet@gcc.gnu.org> | 2009-04-20 10:26:13 +0200 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2009-04-20 10:26:13 +0200 |
commit | 3f25c54d814c705750dc1535dd935b39afc7b779 (patch) | |
tree | bd81a0aab892d56ae076ec2454b8fbf55ef392a2 /gcc/ada/sysdep.c | |
parent | 8dbf3473b19d7579acb40e4f0342d4a1c055e4d5 (diff) | |
download | gcc-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.c | 99 |
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 |