diff --git a/newlib/ChangeLog b/newlib/ChangeLog index e539fc567..cc9fd9168 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,14 @@ +2005-02-25 Eric Blake + + * libc/include/time.h (__tzrule_struct): Make offset long, since + a 16-bit int overflows on a 12-hour offset. + * libc/sys/linux/include/time.h: Ditto. + * libc/time/mktime.c (mktime): Use new type of __tzrule.offset. + * libc/time/mktm_r.c: Ditto. + * libc/time/gettzinfo.c: Ditto. + * libc/time/strftime.c (strftime): Fix '%x' to deal with negative + years. Fix '%z' to use long, not int. + 2005-02-24 Ralf Corsepious * libm/common/s_fpclassify.c: Use __uint32_t instead of int to diff --git a/newlib/libc/include/time.h b/newlib/libc/include/time.h index 83977d2d2..0ef5e958e 100644 --- a/newlib/libc/include/time.h +++ b/newlib/libc/include/time.h @@ -79,7 +79,7 @@ typedef struct __tzrule_struct int d; int s; time_t change; - int offset; + long offset; /* Match type of _timezone. */ } __tzrule_type; typedef struct __tzinfo_struct diff --git a/newlib/libc/sys/linux/include/time.h b/newlib/libc/sys/linux/include/time.h index 0a5279f0b..64ade9463 100644 --- a/newlib/libc/sys/linux/include/time.h +++ b/newlib/libc/sys/linux/include/time.h @@ -92,7 +92,7 @@ typedef struct __tzrule_struct int d; int s; time_t change; - int offset; + long offset; /* Match type of _timezone. */ } __tzrule_type; typedef struct __tzinfo_struct diff --git a/newlib/libc/time/gettzinfo.c b/newlib/libc/time/gettzinfo.c index be754f31b..54c9bc2f0 100644 --- a/newlib/libc/time/gettzinfo.c +++ b/newlib/libc/time/gettzinfo.c @@ -3,8 +3,8 @@ /* Shared timezone information for libc/time functions. */ static __tzinfo_type tzinfo = {1, 0, - { {'J', 0, 0, 0, 0, (time_t)0, 0 }, - {'J', 0, 0, 0, 0, (time_t)0, 0 } + { {'J', 0, 0, 0, 0, (time_t)0, 0L }, + {'J', 0, 0, 0, 0, (time_t)0, 0L } } }; diff --git a/newlib/libc/time/mktime.c b/newlib/libc/time/mktime.c index 8cd9564a9..0ee055cd0 100644 --- a/newlib/libc/time/mktime.c +++ b/newlib/libc/time/mktime.c @@ -211,9 +211,12 @@ mktime (tim_p) { /* calculate start of dst in dst local time and start of std in both std local time and dst local time */ - time_t startdst_dst = tz->__tzrule[0].change - tz->__tzrule[1].offset; - time_t startstd_dst = tz->__tzrule[1].change - tz->__tzrule[1].offset; - time_t startstd_std = tz->__tzrule[1].change - tz->__tzrule[0].offset; + time_t startdst_dst = tz->__tzrule[0].change + - (time_t) tz->__tzrule[1].offset; + time_t startstd_dst = tz->__tzrule[1].change + - (time_t) tz->__tzrule[1].offset; + time_t startstd_std = tz->__tzrule[1].change + - (time_t) tz->__tzrule[0].offset; /* if the time is in the overlap between dst and std local times */ if (tim >= startstd_std && tim < startstd_dst) ; /* we let user decide or leave as -1 */ @@ -226,8 +229,12 @@ mktime (tim_p) if ((isdst ^ tim_p->tm_isdst) == 1) { /* we either subtract or add the difference between - time zone offsets, depending on which way the user got it wrong */ - int diff = tz->__tzrule[0].offset - tz->__tzrule[1].offset; + time zone offsets, depending on which way the user got it + wrong. The diff is typically one hour, or 3600 seconds, + and should fit in a 16-bit int, even though offset + is a long to accomodate 12 hours. */ + int diff = (int) (tz->__tzrule[0].offset + - tz->__tzrule[1].offset); if (!isdst) diff = -diff; tim_p->tm_sec += diff; @@ -240,9 +247,9 @@ mktime (tim_p) /* add appropriate offset to put time in gmt format */ if (isdst == 1) - tim += tz->__tzrule[1].offset; + tim += (time_t) tz->__tzrule[1].offset; else /* otherwise assume std time */ - tim += tz->__tzrule[0].offset; + tim += (time_t) tz->__tzrule[0].offset; /* reset isdst flag to what we have calculated */ tim_p->tm_isdst = isdst; diff --git a/newlib/libc/time/mktm_r.c b/newlib/libc/time/mktm_r.c index 9cea60b7f..4d4b4fab0 100644 --- a/newlib/libc/time/mktm_r.c +++ b/newlib/libc/time/mktm_r.c @@ -95,7 +95,7 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime), if (!is_gmtime) { - int offset; + long offset; int hours, mins, secs; TZ_LOCK; @@ -117,11 +117,11 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime), ? tz->__tzrule[1].offset : tz->__tzrule[0].offset); - hours = offset / SECSPERHOUR; + hours = (int) (offset / SECSPERHOUR); offset = offset % SECSPERHOUR; - mins = offset / SECSPERMIN; - secs = offset % SECSPERMIN; + mins = (int) (offset / SECSPERMIN); + secs = (int) (offset % SECSPERMIN); res->tm_sec -= secs; res->tm_min -= mins; diff --git a/newlib/libc/time/strftime.c b/newlib/libc/time/strftime.c index 2d25890d0..a3fdb745a 100644 --- a/newlib/libc/time/strftime.c +++ b/newlib/libc/time/strftime.c @@ -1,6 +1,7 @@ /* * strftime.c * Original Author: G. Haley + * Additions from: Eric Blake * * Places characters into the array pointed to by s as controlled by the string * pointed to by format. If the total number of resulting characters including @@ -102,9 +103,9 @@ The last two digits of the week-based year, see specifier %G (from o %G The week-based year. In the ISO 8601:2000 calendar, week 1 of the year includes January 4th, and begin on Mondays. Therefore, if January 1st, -2nd, or 3rd falls on a Sunday, that day and earlier belong to week 53 -of the previous year; and if December 29th, 30th, or 31st falls on -Monday, that day and later belong to week 1 of the next year. For +2nd, or 3rd falls on a Sunday, that day and earlier belong to the last +week of the previous year; and if December 29th, 30th, or 31st falls +on Monday, that day and later belong to week 1 of the next year. For consistency with %Y, it always has at least four characters. Example: "%G" for Saturday 2nd January 1999 gives "1998", and for Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday] @@ -447,7 +448,8 @@ _DEFUN (strftime, (s, maxsize, format, tim_p), { sprintf (&s[count], "%.2d/%.2d/%.2d", tim_p->tm_mon + 1, tim_p->tm_mday, - (tim_p->tm_year % 100 + 100) % 100); + tim_p->tm_year >= 0 ? tim_p->tm_year % 100 + : abs (tim_p->tm_year + YEAR_BASE) % 100); count += 8; } else @@ -756,7 +758,7 @@ _DEFUN (strftime, (s, maxsize, format, tim_p), { if (count < maxsize - 5) { - int offset; + long offset; __tzinfo_type *tz = __gettzinfo (); TZ_LOCK; /* The sign of this is exactly opposite the envvar TZ. We @@ -764,8 +766,8 @@ _DEFUN (strftime, (s, maxsize, format, tim_p), but have to use __tzrule for daylight savings. */ offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset; TZ_UNLOCK; - sprintf (&s[count], "%+03ld%.2d", offset / SECSPERHOUR, - abs (offset / SECSPERMIN) % 60); + sprintf (&s[count], "%+03ld%.2ld", offset / SECSPERHOUR, + labs (offset / SECSPERMIN) % 60L); count += 5; } else