/* 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 <eggert@twinsun.com>.
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
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 <config.h>
#endif
# define LEAP_SECONDS_POSSIBLE 1
#endif
-#include <sys/types.h> /* Some systems define `time_t' here. */
#include <time.h>
#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 */
an integer. */
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
-/* True if negative values of the integer type T use twos complement
- representation. */
-#define TYPE_TWOS_COMPLEMENT(t) ((t) - (t) 1 == (t) ((t) ~ (t) 1 + (t) 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. */
#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
- (i.e., bits that do not contribute to the value), or if T uses
- signed-magnitude representation. 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 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
-#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+ 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))))
#ifndef TIME_T_MIN
# define TIME_T_MIN TYPE_MINIMUM (time_t)
#ifndef _LIBC
-/* Portable standalone applications should supply a "time_r.h" that
+/* Portable standalone applications should supply a <time.h> 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
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. */
/* 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.
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
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;
}
/* The last conversion attempt failed;
revert to the most recent successful attempt. */
*t = ok;
- *tp = tm;
- r = tp;
+ r = convert (t, 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;
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;
}