1# serial 25 2dnl Copyright (C) 2002-2003, 2005-2007, 2009-2015 Free Software Foundation, 3dnl Inc. 4dnl This file is free software; the Free Software Foundation 5dnl gives unlimited permission to copy and/or distribute it, 6dnl with or without modifications, as long as this notice is preserved. 7 8dnl From Jim Meyering. 9 10AC_DEFUN([gl_FUNC_MKTIME], 11[ 12 AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS]) 13 14 dnl We don't use AC_FUNC_MKTIME any more, because it is no longer maintained 15 dnl in Autoconf and because it invokes AC_LIBOBJ. 16 AC_CHECK_HEADERS_ONCE([unistd.h]) 17 AC_CHECK_DECLS_ONCE([alarm]) 18 AC_REQUIRE([gl_MULTIARCH]) 19 if test $APPLE_UNIVERSAL_BUILD = 1; then 20 # A universal build on Apple Mac OS X platforms. 21 # The test result would be 'yes' in 32-bit mode and 'no' in 64-bit mode. 22 # But we need a configuration result that is valid in both modes. 23 gl_cv_func_working_mktime=no 24 fi 25 AC_CACHE_CHECK([for working mktime], [gl_cv_func_working_mktime], 26 [AC_RUN_IFELSE( 27 [AC_LANG_SOURCE( 28[[/* Test program from Paul Eggert and Tony Leneis. */ 29#include <limits.h> 30#include <stdlib.h> 31#include <time.h> 32 33#ifdef HAVE_UNISTD_H 34# include <unistd.h> 35#endif 36 37#if HAVE_DECL_ALARM 38# include <signal.h> 39#endif 40 41/* Work around redefinition to rpl_putenv by other config tests. */ 42#undef putenv 43 44static time_t time_t_max; 45static time_t time_t_min; 46 47/* Values we'll use to set the TZ environment variable. */ 48static char *tz_strings[] = { 49 (char *) 0, "TZ=GMT0", "TZ=JST-9", 50 "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" 51}; 52#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0])) 53 54/* Return 0 if mktime fails to convert a date in the spring-forward gap. 55 Based on a problem report from Andreas Jaeger. */ 56static int 57spring_forward_gap () 58{ 59 /* glibc (up to about 1998-10-07) failed this test. */ 60 struct tm tm; 61 62 /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" 63 instead of "TZ=America/Vancouver" in order to detect the bug even 64 on systems that don't support the Olson extension, or don't have the 65 full zoneinfo tables installed. */ 66 putenv ("TZ=PST8PDT,M4.1.0,M10.5.0"); 67 68 tm.tm_year = 98; 69 tm.tm_mon = 3; 70 tm.tm_mday = 5; 71 tm.tm_hour = 2; 72 tm.tm_min = 0; 73 tm.tm_sec = 0; 74 tm.tm_isdst = -1; 75 return mktime (&tm) != (time_t) -1; 76} 77 78static int 79mktime_test1 (time_t now) 80{ 81 struct tm *lt; 82 return ! (lt = localtime (&now)) || mktime (lt) == now; 83} 84 85static int 86mktime_test (time_t now) 87{ 88 return (mktime_test1 (now) 89 && mktime_test1 ((time_t) (time_t_max - now)) 90 && mktime_test1 ((time_t) (time_t_min + now))); 91} 92 93static int 94irix_6_4_bug () 95{ 96 /* Based on code from Ariel Faigon. */ 97 struct tm tm; 98 tm.tm_year = 96; 99 tm.tm_mon = 3; 100 tm.tm_mday = 0; 101 tm.tm_hour = 0; 102 tm.tm_min = 0; 103 tm.tm_sec = 0; 104 tm.tm_isdst = -1; 105 mktime (&tm); 106 return tm.tm_mon == 2 && tm.tm_mday == 31; 107} 108 109static int 110bigtime_test (int j) 111{ 112 struct tm tm; 113 time_t now; 114 tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; 115 now = mktime (&tm); 116 if (now != (time_t) -1) 117 { 118 struct tm *lt = localtime (&now); 119 if (! (lt 120 && lt->tm_year == tm.tm_year 121 && lt->tm_mon == tm.tm_mon 122 && lt->tm_mday == tm.tm_mday 123 && lt->tm_hour == tm.tm_hour 124 && lt->tm_min == tm.tm_min 125 && lt->tm_sec == tm.tm_sec 126 && lt->tm_yday == tm.tm_yday 127 && lt->tm_wday == tm.tm_wday 128 && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) 129 == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) 130 return 0; 131 } 132 return 1; 133} 134 135static int 136year_2050_test () 137{ 138 /* The correct answer for 2050-02-01 00:00:00 in Pacific time, 139 ignoring leap seconds. */ 140 unsigned long int answer = 2527315200UL; 141 142 struct tm tm; 143 time_t t; 144 tm.tm_year = 2050 - 1900; 145 tm.tm_mon = 2 - 1; 146 tm.tm_mday = 1; 147 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 148 tm.tm_isdst = -1; 149 150 /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" 151 instead of "TZ=America/Vancouver" in order to detect the bug even 152 on systems that don't support the Olson extension, or don't have the 153 full zoneinfo tables installed. */ 154 putenv ("TZ=PST8PDT,M4.1.0,M10.5.0"); 155 156 t = mktime (&tm); 157 158 /* Check that the result is either a failure, or close enough 159 to the correct answer that we can assume the discrepancy is 160 due to leap seconds. */ 161 return (t == (time_t) -1 162 || (0 < t && answer - 120 <= t && t <= answer + 120)); 163} 164 165int 166main () 167{ 168 int result = 0; 169 time_t t, delta; 170 int i, j; 171 int time_t_signed_magnitude = (time_t) ~ (time_t) 0 < (time_t) -1; 172 int time_t_signed = ! ((time_t) 0 < (time_t) -1); 173 174#if HAVE_DECL_ALARM 175 /* This test makes some buggy mktime implementations loop. 176 Give up after 60 seconds; a mktime slower than that 177 isn't worth using anyway. */ 178 signal (SIGALRM, SIG_DFL); 179 alarm (60); 180#endif 181 182 time_t_max = (! time_t_signed 183 ? (time_t) -1 184 : ((((time_t) 1 << (sizeof (time_t) * CHAR_BIT - 2)) - 1) 185 * 2 + 1)); 186 time_t_min = (! time_t_signed 187 ? (time_t) 0 188 : time_t_signed_magnitude 189 ? ~ (time_t) 0 190 : ~ time_t_max); 191 192 delta = time_t_max / 997; /* a suitable prime number */ 193 for (i = 0; i < N_STRINGS; i++) 194 { 195 if (tz_strings[i]) 196 putenv (tz_strings[i]); 197 198 for (t = 0; t <= time_t_max - delta && (result & 1) == 0; t += delta) 199 if (! mktime_test (t)) 200 result |= 1; 201 if ((result & 2) == 0 202 && ! (mktime_test ((time_t) 1) 203 && mktime_test ((time_t) (60 * 60)) 204 && mktime_test ((time_t) (60 * 60 * 24)))) 205 result |= 2; 206 207 for (j = 1; (result & 4) == 0; j <<= 1) 208 { 209 if (! bigtime_test (j)) 210 result |= 4; 211 if (INT_MAX / 2 < j) 212 break; 213 } 214 if ((result & 8) == 0 && ! bigtime_test (INT_MAX)) 215 result |= 8; 216 } 217 if (! irix_6_4_bug ()) 218 result |= 16; 219 if (! spring_forward_gap ()) 220 result |= 32; 221 if (! year_2050_test ()) 222 result |= 64; 223 return result; 224}]])], 225 [gl_cv_func_working_mktime=yes], 226 [gl_cv_func_working_mktime=no], 227 [gl_cv_func_working_mktime=no]) 228 ]) 229 230 if test $gl_cv_func_working_mktime = no; then 231 REPLACE_MKTIME=1 232 else 233 REPLACE_MKTIME=0 234 fi 235]) 236 237AC_DEFUN([gl_FUNC_MKTIME_INTERNAL], [ 238 AC_REQUIRE([gl_FUNC_MKTIME]) 239 if test $REPLACE_MKTIME = 0; then 240 dnl BeOS has __mktime_internal in libc, but other platforms don't. 241 AC_CHECK_FUNC([__mktime_internal], 242 [AC_DEFINE([mktime_internal], [__mktime_internal], 243 [Define to the real name of the mktime_internal function.]) 244 ], 245 [dnl mktime works but it doesn't export __mktime_internal, 246 dnl so we need to substitute our own mktime implementation. 247 REPLACE_MKTIME=1 248 ]) 249 fi 250]) 251 252# Prerequisites of lib/mktime.c. 253AC_DEFUN([gl_PREREQ_MKTIME], [:]) 254