diff options
Diffstat (limited to 'time/mktime.c')
-rw-r--r-- | time/mktime.c | 73 |
1 files changed, 25 insertions, 48 deletions
diff --git a/time/mktime.c b/time/mktime.c index 8f00c72..c6ae56e 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -1,7 +1,7 @@ /* Convert a `struct tm' to a time_t value. - Copyright (C) 1993-1999, 2002-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1993-1999, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Paul Eggert <eggert@twinsun.com>. + Contributed by Paul Eggert (eggert@twinsun.com). The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -38,11 +38,10 @@ #include <limits.h> -#include <string.h> /* For the real memcpy prototype. */ - #if DEBUG # include <stdio.h> # include <stdlib.h> +# include <string.h> /* Make it work even if the system's libc has its own mktime routine. */ # define mktime my_mktime #endif /* DEBUG */ @@ -62,38 +61,13 @@ ? (a) >> (b) \ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0)) -/* The extra casts in the following macros work around compiler bugs, - e.g., in Cray C 5.0.3.0. */ - -/* True if the arithmetic type T is an integer type. bool counts as - an integer. */ -#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) - -/* 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) -#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) - -/* True if the arithmetic type T is signed. */ +/* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) - -/* The maximum and minimum values for the integer type T. These - macros have undefined behavior if T is signed and has padding bits. - If this is a problem for you, please let us know how to fix it for - your host. */ -#define TYPE_MINIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) 0 \ - : TYPE_SIGNED_MAGNITUDE (t) \ - ? ~ (t) 0 \ - : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) -#define TYPE_MAXIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) -1 \ - : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) +/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. + It is necessary at least when t == time_t. */ +#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) +#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) #ifndef TIME_T_MIN # define TIME_T_MIN TYPE_MINIMUM (time_t) @@ -106,8 +80,8 @@ /* 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)); +verify (time_t_is_integer, (time_t) 0.5 == 0); +verify (twos_complement_arithmetic, -1 == ~1 + 1); /* The code also assumes that signed integer overflow silently wraps around, but this assumption can't be stated without causing a diagnostic on some hosts. */ @@ -216,11 +190,10 @@ 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; and don't oscillate between two values, as that would - confuse the spring-forward gap detector. */ + match. */ return (*t < TIME_T_MIDPOINT - ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN) - : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX)); + ? TIME_T_MIN + (*t == TIME_T_MIN) + : TIME_T_MAX - (*t == TIME_T_MAX)); } /* Use CONVERT to convert *T to a broken down time in *TP. @@ -230,12 +203,13 @@ static struct tm * ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), time_t *t, struct tm *tp) { - struct tm *r = convert (t, tp); + struct tm *r; - if (!r && *t) + if (! (r = (*convert) (t, tp)) && *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 @@ -245,9 +219,11 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), time_t mid = *t = (bad < 0 ? bad + ((ok - bad) >> 1) : ok + ((bad - ok) >> 1)); - r = convert (t, tp); - if (r) - ok = mid; + if ((r = (*convert) (t, tp))) + { + tm = *r; + ok = mid; + } else bad = mid; } @@ -257,7 +233,8 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), /* The last conversion attempt failed; revert to the most recent successful attempt. */ *t = ok; - r = convert (t, tp); + *tp = tm; + r = tp; } } @@ -486,7 +463,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; } |