]> Savannah Git Hosting - gnulib.git/commitdiff
mktime: Work around TZ problem on native Windows.
authorBruno Haible <bruno@clisp.org>
Sun, 30 Apr 2017 14:34:54 +0000 (16:34 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 30 Apr 2017 17:26:38 +0000 (19:26 +0200)
* 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.

ChangeLog
doc/posix-functions/mktime.texi
lib/mktime.c
m4/mktime.m4
m4/timegm.m4
modules/mktime-internal

index af7f731c4ee269af2b2e0169ae3214d928f85e34..01cc13788fdf8925e1c10882167184d92a543c94 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+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.
index ffb7b79e117fd4d317c8ccc52fa560a84ad91446..35a9a41e7e7b8a4f02930282c835e0c5eb46a4b6 100644 (file)
@@ -9,6 +9,9 @@ Gnulib module: mktime
 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.
@@ -16,7 +19,4 @@ Portability problems fixed by Gnulib:
 
 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
index 2efd44a226803003fdeaad620ff2bdb039f909d5..a78d960e53291f705fa11d6a64de62b76a9ce5b2 100644 (file)
 # 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
@@ -458,25 +478,46 @@ __mktime_internal (struct tm *tp,
   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
index d594ddc58be24cdc665168474a8b65b83723455c..31da65e8b2d2ebe0956488c3d7907705b03d1016 100644 (file)
@@ -1,4 +1,4 @@
-# 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
@@ -21,9 +21,9 @@ AC_DEFUN([gl_TIME_T_IS_SIGNED],
   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
@@ -239,29 +239,50 @@ main ()
 }]])],
        [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.
index 510e25ab4b0f5043f9c2d737e12c89ba41f4e387..1f18552e9f58bea3f87f4654dc9927d52fddb264 100644 (file)
@@ -1,4 +1,4 @@
-# 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,
@@ -7,11 +7,11 @@ dnl with or without modifications, as long as this notice is preserved.
 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
index f9cf4600d12315226f5f9eb9d1edc5a13d48c04f..1465c90dcd5defded0504171f4d58c3a2453e96e 100644 (file)
@@ -10,7 +10,7 @@ mktime
 
 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