-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Paul Eggert (eggert@twinsun.com).
-This file is part of the GNU C Library.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+ 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 the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
+ 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. */
/* Define this to have a standalone program to test this implementation of
mktime. */
#include <config.h>
#endif
+#ifdef _LIBC
+# define HAVE_LIMITS_H 1
+# define HAVE_LOCALTIME_R 1
+# define STDC_HEADERS 1
+#endif
+
/* Assume that leap seconds are possible, unless told otherwise.
If the host has a `zic' command with a `-L leapsecondfilename' option,
then it supports leap seconds; otherwise it probably doesn't. */
#include <sys/types.h> /* Some systems define `time_t' here. */
#include <time.h>
-#if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
+#if HAVE_LIMITS_H
#include <limits.h>
#endif
#if DEBUG
#include <stdio.h>
-#if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
+#if STDC_HEADERS
#include <stdlib.h>
#endif
/* Make it work even if the system's libc has its own mktime routine. */
#endif
#ifndef TIME_T_MIN
-#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
- : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
+/* The outer cast to time_t works around a bug in Cray C 5.0.3.0. */
+#define TIME_T_MIN ((time_t) \
+ (0 < (time_t) -1 ? (time_t) 0 \
+ : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
#endif
#ifndef TIME_T_MAX
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
time_t *));
-#if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
#ifdef _LIBC
#define localtime_r __localtime_r
#else
+#if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
/* Approximate localtime_r as best we can in its absence. */
#define localtime_r my_localtime_r
static struct tm *localtime_r __P ((const time_t *, struct tm *));
*tp = *l;
return tp;
}
-#endif /* ! _LIBC */
#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
+#endif /* ! _LIBC */
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
int year, yday, hour, min, sec;
const struct tm *tp;
{
- time_t ay = year + (time_t) (TM_YEAR_BASE - 1);
- time_t by = tp->tm_year + (time_t) (TM_YEAR_BASE - 1);
- time_t intervening_leap_days =
- (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
- time_t years = ay - by;
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid int overflow. time_t overflow is OK, since
+ only the low order bits of the correct time_t answer are needed.
+ Don't convert to time_t until after all divisions are done, since
+ time_t might be unsigned. */
+ int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
+ int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = a100 >> 2;
+ int b400 = b100 >> 2;
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+ time_t years = year - (time_t) tp->tm_year;
time_t days = (365 * years + intervening_leap_days
+ (yday - tp->tm_yday));
return (60 * (60 * (24 * days + (hour - tp->tm_hour))
}
+static time_t localtime_offset;
+
/* Convert *TP to a time_t value. */
time_t
mktime (tp)
struct tm *tp;
{
- static time_t localtime_offset;
+#ifdef _LIBC
+ /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+ time zone names contained in the external variable `tzname' shall
+ be set as if the tzset() function had been called. */
+ __tzset ();
+#endif
+
return __mktime_internal (tp, localtime_r, &localtime_offset);
}