X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmktime.c;h=a42c771542023520f20b6a984e35d49f17dafc83;hb=ce8d6d06c84df409ebb0d71478a122f48cff3dc6;hp=300607c4ba8343885582f71beef004926397cbe3;hpb=f77aebf866032522e6a2c8b0d36a587f6aeccbe4;p=gnulib.git diff --git a/lib/mktime.c b/lib/mktime.c index 300607c4b..a42c77154 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -1,8 +1,7 @@ /* Convert a `struct tm' to a time_t value. - Copyright (C) 1993-1999, 2002, 2003, 2004, 2005 Free Software Foundation, - Inc. + Copyright (C) 1993-1999, 2002-2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Paul Eggert (eggert@twinsun.com). + Contributed by Paul Eggert . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,13 +15,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Define this to have a standalone program to test this implementation of mktime. */ /* #define DEBUG 1 */ -#ifdef HAVE_CONFIG_H +#ifndef _LIBC # include #endif @@ -33,15 +32,15 @@ # define LEAP_SECONDS_POSSIBLE 1 #endif -#include /* Some systems define `time_t' here. */ #include #include +#include /* For the real memcpy prototype. */ + #if DEBUG # include # include -# include /* Make it work even if the system's libc has its own mktime routine. */ # define mktime my_mktime #endif /* DEBUG */ @@ -68,9 +67,9 @@ an integer. */ #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) -/* True if negative values of the signed integer type T use twos - complement, ones complement, or signed magnitude representation, - respectively. Much GNU code assumes twos complement, but some +/* True if negative values of the signed integer type T use two's + complement, ones' complement, or signed magnitude representation, + respectively. Much GNU code assumes two's complement, but some people like to be portable to all possible C hosts. */ #define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) #define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) @@ -141,11 +140,10 @@ const unsigned short int __mon_yday[2][13] = #ifndef _LIBC -/* Portable standalone applications should supply a "time_r.h" that +/* Portable standalone applications should supply a that declares a POSIX-compliant localtime_r, for the benefit of older implementations that lack localtime_r or have a nonstandard one. See the gnulib time_r module for one way to implement this. */ -# include "time_r.h" # undef __localtime_r # define __localtime_r localtime_r # define __mktime_internal mktime_internal @@ -167,8 +165,11 @@ ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, int year0, int yday0, int hour0, int min0, int sec0) { verify (C99_integer_division, -1 / 2 == 0); +#if 0 /* This assertion fails on 32-bit systems with 64-bit time_t, such as + NetBSD 5 on i386. */ verify (long_int_year_and_yday_are_wide_enough, INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX); +#endif /* Compute intervening leap days correctly even if year is negative. Take care to avoid integer overflow here. */ @@ -215,10 +216,11 @@ guess_time_tm (long int year, long int yday, int hour, int min, int sec, /* Overflow occurred one way or another. Return the nearest result that is actually in range, except don't report a zero difference if the actual difference is nonzero, as that would cause a false - match. */ + match; and don't oscillate between two values, as that would + confuse the spring-forward gap detector. */ return (*t < TIME_T_MIDPOINT - ? TIME_T_MIN + (*t == TIME_T_MIN) - : TIME_T_MAX - (*t == TIME_T_MAX)); + ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN) + : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX)); } /* Use CONVERT to convert *T to a broken down time in *TP. @@ -228,13 +230,12 @@ static struct tm * ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), time_t *t, struct tm *tp) { - struct tm *r; + struct tm *r = convert (t, tp); - if (! (r = (*convert) (t, tp)) && *t) + if (!r && *t) { time_t bad = *t; time_t ok = 0; - struct tm tm; /* BAD is a known unconvertible time_t, and OK is a known good one. Use binary search to narrow the range between BAD and OK until @@ -244,11 +245,9 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), time_t mid = *t = (bad < 0 ? bad + ((ok - bad) >> 1) : ok + ((bad - ok) >> 1)); - if ((r = (*convert) (t, tp))) - { - tm = *r; - ok = mid; - } + r = convert (t, tp); + if (r) + ok = mid; else bad = mid; } @@ -258,8 +257,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), /* The last conversion attempt failed; revert to the most recent successful attempt. */ *t = ok; - *tp = tm; - r = tp; + r = convert (t, tp); } } @@ -295,7 +293,9 @@ __mktime_internal (struct tm *tp, int mday = tp->tm_mday; int mon = tp->tm_mon; int year_requested = tp->tm_year; - int isdst = tp->tm_isdst; + /* Normalize the value. */ + int isdst = ((tp->tm_isdst >> (8 * sizeof (tp->tm_isdst) - 1)) + | (tp->tm_isdst != 0)); /* 1 if the previous probe was DST. */ int dst2; @@ -488,7 +488,7 @@ __mktime_internal (struct tm *tp, t2 = t1 + sec_adjustment; if (((t1 < t) != (sec_requested < 0)) | ((t2 < t1) != (sec_adjustment < 0)) - | ! (*convert) (&t2, &tm)) + | ! convert (&t2, &tm)) return -1; t = t2; }