X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmktime.c;h=34112a9a08f01f4ef70387ba7e7779401b31fc8c;hb=58dc681a9b810db4f7fc8b47d6c216bb169b7da4;hp=852d4058b958c46108e930bae4db2f397dce0325;hpb=870b659d41f48c3feee7ee6d812ac8e21dcebc69;p=gnulib.git diff --git a/lib/mktime.c b/lib/mktime.c index 852d4058b..34112a9a0 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -1,22 +1,22 @@ -/* 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. */ @@ -26,6 +26,12 @@ Cambridge, MA 02139, USA. */ #include #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. */ @@ -36,13 +42,13 @@ Cambridge, MA 02139, USA. */ #include /* Some systems define `time_t' here. */ #include -#if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS +#if HAVE_LIMITS_H #include #endif #if DEBUG #include -#if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS +#if STDC_HEADERS #include #endif /* Make it work even if the system's libc has its own mktime routine. */ @@ -69,8 +75,10 @@ Cambridge, MA 02139, USA. */ #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) @@ -101,10 +109,10 @@ time_t __mktime_internal __P ((struct tm *, 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 *)); @@ -119,8 +127,8 @@ localtime_r (t, tp) *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), @@ -133,11 +141,19 @@ ydhms_tm_diff (year, yday, hour, min, sec, 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)) @@ -146,12 +162,20 @@ ydhms_tm_diff (year, yday, hour, min, sec, tp) } +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); }