+2017-04-30 Bruno Haible <bruno@clisp.org>
+
+ mktime: Work around TZ problem on native Windows.
+ * lib/mktime.c: Add #ifs to make the algorithmic workaround independent
+ from the native Windows workaround.
+ * m4/mktime.m4 (gl_FUNC_MKTIME_WORKS): New macro, extracted from
+ gl_FUNC_MKTIME. If guessing, set gl_cv_func_working_mktime to
+ 'guessing no'.
+ (gl_FUNC_MKTIME): Require it. Require AC_CANONICAL_HOST.
+ Set REPLACE_MKTIME to 1 on native Windows. Define NEED_MKTIME_WORKING,
+ NEED_MKTIME_WINDOWS.
+ (gl_FUNC_MKTIME_INTERNAL): Require gl_FUNC_MKTIME_WORKS, not
+ gl_FUNC_MKTIME. Set WANT_MKTIME_INTERNAL, not REPLACE_MKTIME. Define
+ NEED_MKTIME_INTERNAL.
+ * m4/timegm.m4 (gl_FUNC_TIMEGM): Require gl_FUNC_MKTIME_WORKS, not
+ gl_FUNC_MKTIME. Cope with 'guessing yes' value.
+ * modules/mktime-internal (configure.ac): Test WANT_MKTIME_INTERNAL,
+ not REPLACE_MKTIME.
+ * doc/posix-functions/mktime.texi: Mention the native Windows
+ workaround.
+
2017-04-30 Bruno Haible <bruno@clisp.org>
localtime: New module.
Portability problems fixed by Gnulib:
@itemize
@item
+On native Windows platforms (mingw, MSVC), this function works incorrectly
+when the environment variable @code{TZ} has been set by Cygwin.
+@item
@code{mktime} may go into an endless loop on some platforms.
@item
@code{mktime} may occasionally return wrong results on some platforms.
Portability problems not fixed by Gnulib:
@itemize
-@item
-On native Windows platforms (mingw, MSVC), this function works incorrectly
-when the environment variable @code{TZ} has been set by Cygwin.
@end itemize
# define DEBUG_MKTIME 0
#endif
+/* The following macros influence what gets defined when this file is compiled:
+
+ Macro/expression Which gnulib module This compilation unit
+ should define
+
+ NEED_MKTIME_WORKING mktime rpl_mktime
+ || NEED_MKTIME_WINDOWS
+
+ NEED_MKTIME_INTERNAL mktime-internal mktime_internal
+
+ DEBUG_MKTIME (defined manually) my_mktime, main
+ */
+
#if !defined _LIBC && !DEBUG_MKTIME
# include <config.h>
#endif
# define mktime my_mktime
#endif
+#if NEED_MKTIME_WINDOWS /* on native Windows */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#if NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME
+
/* A signed type that can represent an integer number of years
multiplied by three times the number of seconds in a year. It is
needed when converting a tm_year value times the number of seconds
return t;
}
+#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME */
+
+#if NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME
+# if NEED_MKTIME_WORKING || DEBUG_MKTIME
static mktime_offset_t localtime_offset;
+# endif
/* Convert *TP to a time_t value. */
time_t
mktime (struct tm *tp)
{
-#ifdef _LIBC
+# if NEED_MKTIME_WINDOWS
+ /* If the environment variable TZ has been set by Cygwin, neutralize it.
+ The Microsoft CRT interprets TZ differently than Cygwin and produces
+ incorrect results if TZ has the syntax used by Cygwin. */
+ const char *tz = getenv ("TZ");
+ if (tz != NULL && strchr (tz, '/') != NULL)
+ _putenv ("TZ=");
+# endif
+
+# if NEED_MKTIME_WORKING || DEBUG_MKTIME
+# 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 ();
-#elif HAVE_TZSET
+# elif HAVE_TZSET
tzset ();
-#endif
+# endif
return __mktime_internal (tp, __localtime_r, &localtime_offset);
+# else
+# undef mktime
+ return mktime (tp);
+# endif
}
+#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME */
+
#ifdef weak_alias
weak_alias (mktime, timelocal)
#endif
-# serial 27
+# serial 28
dnl Copyright (C) 2002-2003, 2005-2007, 2009-2017 Free Software Foundation,
dnl Inc.
dnl This file is free software; the Free Software Foundation
fi
])
-AC_DEFUN([gl_FUNC_MKTIME],
+dnl Test whether mktime works. Set gl_cv_func_working_mktime.
+AC_DEFUN([gl_FUNC_MKTIME_WORKS],
[
- AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
AC_REQUIRE([gl_TIME_T_IS_SIGNED])
dnl We don't use AC_FUNC_MKTIME any more, because it is no longer maintained
}]])],
[gl_cv_func_working_mktime=yes],
[gl_cv_func_working_mktime=no],
- [gl_cv_func_working_mktime=no])
+ [gl_cv_func_working_mktime="guessing no"])
])
+])
+
+dnl Main macro of module 'mktime'.
+AC_DEFUN([gl_FUNC_MKTIME],
+[
+ AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([gl_FUNC_MKTIME_WORKS])
- if test $gl_cv_func_working_mktime = no; then
+ REPLACE_MKTIME=0
+ if test "$gl_cv_func_working_mktime" != yes; then
REPLACE_MKTIME=1
- else
- REPLACE_MKTIME=0
+ AC_DEFINE([NEED_MKTIME_WORKING], [1],
+ [Define if the compilation of mktime.c should define 'mktime'
+ with the algorithmic workarounds.])
fi
+ case "$host_os" in
+ mingw*)
+ REPLACE_MKTIME=1
+ AC_DEFINE([NEED_MKTIME_WINDOWS], [1],
+ [Define if the compilation of mktime.c should define 'mktime'
+ with the native Windows TZ workaround.])
+ ;;
+ esac
])
+dnl Main macro of module 'mktime-internal'.
AC_DEFUN([gl_FUNC_MKTIME_INTERNAL], [
- AC_REQUIRE([gl_FUNC_MKTIME])
- if test $REPLACE_MKTIME = 0; then
- dnl BeOS has __mktime_internal in libc, but other platforms don't.
- AC_CHECK_FUNC([__mktime_internal],
- [AC_DEFINE([mktime_internal], [__mktime_internal],
- [Define to the real name of the mktime_internal function.])
- ],
- [dnl mktime works but it doesn't export __mktime_internal,
- dnl so we need to substitute our own mktime implementation.
- REPLACE_MKTIME=1
- ])
- fi
+ AC_REQUIRE([gl_FUNC_MKTIME_WORKS])
+
+ WANT_MKTIME_INTERNAL=0
+ dnl BeOS has __mktime_internal in libc, but other platforms don't.
+ AC_CHECK_FUNC([__mktime_internal],
+ [AC_DEFINE([mktime_internal], [__mktime_internal],
+ [Define to the real name of the mktime_internal function.])
+ ],
+ [dnl mktime works but it doesn't export __mktime_internal,
+ dnl so we need to substitute our own mktime implementation.
+ WANT_MKTIME_INTERNAL=1
+ AC_DEFINE([NEED_MKTIME_INTERNAL], [1],
+ [Define if the compilation of mktime.c should define 'mktime_internal'.])
+ ])
])
# Prerequisites of lib/mktime.c.
-# timegm.m4 serial 11
+# timegm.m4 serial 12
dnl Copyright (C) 2003, 2007, 2009-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
AC_DEFUN([gl_FUNC_TIMEGM],
[
AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
- AC_REQUIRE([gl_FUNC_MKTIME])
+ AC_REQUIRE([gl_FUNC_MKTIME_WORKS])
REPLACE_TIMEGM=0
AC_CHECK_FUNCS_ONCE([timegm])
if test $ac_cv_func_timegm = yes; then
- if test $gl_cv_func_working_mktime = no; then
+ if test "$gl_cv_func_working_mktime" != yes; then
# Assume that timegm is buggy if mktime is.
REPLACE_TIMEGM=1
fi
configure.ac:
gl_FUNC_MKTIME_INTERNAL
-if test $REPLACE_MKTIME = 1; then
+if test $WANT_MKTIME_INTERNAL = 1; then
AC_LIBOBJ([mktime])
gl_PREREQ_MKTIME
fi