X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fmktime.c;h=cba2b8b322e9e245c5c99a2e2352cd041f0cbb6d;hb=5bf4ad0bfa91baa20e4f39f47bfb8b4dd00df720;hp=6eb9bfc72ddd64d4e04ca459785de4edaada43a9;hpb=385b9f9d098b636827593dbd0f813c2b6858b308;p=gnulib.git diff --git a/lib/mktime.c b/lib/mktime.c index 6eb9bfc72..cba2b8b32 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -60,15 +60,20 @@ # include # include /* Make it work even if the system's libc has its own mktime routine. */ +# undef mktime # define mktime my_mktime #endif /* DEBUG */ +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + /* A signed type that is at least one bit wider than int. */ #if INT_MAX <= LONG_MAX / 2 typedef long int long_int; #else typedef long long int long_int; #endif +verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2); /* Shift A right by B bits portably, by dividing A by 2**B and truncating towards minus infinity. A and B should be free of side @@ -112,7 +117,7 @@ typedef long long int long_int; #define TYPE_MAXIMUM(t) \ ((t) (! TYPE_SIGNED (t) \ ? (t) -1 \ - : (((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) << 1) + 1))) + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) #ifndef TIME_T_MIN # define TIME_T_MIN TYPE_MINIMUM (time_t) @@ -122,9 +127,6 @@ typedef long long int long_int; #endif #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1) -/* Verify a requirement at compile-time (unlike assert, which is runtime). */ -#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } - verify (time_t_is_integer, TYPE_IS_INTEGER (time_t)); verify (twos_complement_arithmetic, (TYPE_TWOS_COMPLEMENT (int) @@ -171,6 +173,14 @@ const unsigned short int __mon_yday[2][13] = # include "mktime-internal.h" #endif +/* Return 1 if the values A and B differ according to the rules for + tm_isdst: A and B differ if one is zero and the other positive. */ +static int +isdst_differ (int a, int b) +{ + return (!a != !b) & (0 <= a) & (0 <= b); +} + /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks were not adjusted between the time stamps. @@ -187,8 +197,6 @@ 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); - verify (long_int_year_and_yday_are_wide_enough, - INT_MAX == INT_MAX * (long_int) 2 / 2); /* Compute intervening leap days correctly even if year is negative. Take care to avoid integer overflow here. */ @@ -356,9 +364,7 @@ __mktime_internal (struct tm *tp, int mday = tp->tm_mday; int mon = tp->tm_mon; int year_requested = tp->tm_year; - /* Normalize the value. */ - int isdst = ((tp->tm_isdst >> (8 * sizeof (tp->tm_isdst) - 1)) - | (tp->tm_isdst != 0)); + int isdst = tp->tm_isdst; /* 1 if the previous probe was DST. */ int dst2; @@ -488,7 +494,7 @@ __mktime_internal (struct tm *tp, /* We have a match. Check whether tm.tm_isdst has the requested value, if any. */ - if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst) + if (isdst_differ (isdst, tm.tm_isdst)) { /* tm.tm_isdst has the wrong value. Look for a neighboring time with the right value, and use its UTC offset. @@ -526,7 +532,7 @@ __mktime_internal (struct tm *tp, time_t ot = t + delta * direction; struct tm otm; ranged_convert (convert, &ot, &otm); - if (otm.tm_isdst == isdst) + if (! isdst_differ (isdst, otm.tm_isdst)) { /* We found the desired tm_isdst. Extrapolate back to the desired time. */ @@ -602,7 +608,7 @@ not_equal_tm (const struct tm *a, const struct tm *b) | (a->tm_mon ^ b->tm_mon) | (a->tm_year ^ b->tm_year) | (a->tm_yday ^ b->tm_yday) - | (a->tm_isdst ^ b->tm_isdst)); + | isdst_differ (a->tm_isdst, b->tm_isdst)); } static void @@ -726,6 +732,6 @@ main (int argc, char **argv) /* Local Variables: -compile-command: "gcc -DDEBUG -Wall -W -O2 -g mktime.c -o mktime" +compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime" End: */