Resolve conflicts for functions introduced in Android API level 35.
+ Reported by Po Lu <luangruo@yahoo.com> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2024-09/msg00024.html>.
+ * lib/time.in.h (timezone_t, tzalloc, tzfree): Don't require _GNU_SOURCE
+ to be defined. Define depending on HAVE_TZALLOC, not HAVE_TIMEZONE_T.
+ (localtime_rz, mktime_z): Likewise. Override if REPLACE_LOCALTIME_RZ or
+ REPLACE_MKTIME_Z is 1, respectively.
+ * lib/time_rz.c: If NEED_TIMEZONE_NULL_SUPPORT, define only localtime_rz
+ and mktime_z and only as wrappers around the system function.
+ * m4/time_h.m4 (gl_TIME_H_DEFAULTS): Initialize HAVE_TZALLOC,
+ REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z.
+ * m4/time_rz.m4 (gl_TIME_RZ): Conditionally set HAVE_TZALLOC,
+ REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Conditionally define
+ NEED_TIMEZONE_NULL_SUPPORT.
+ * modules/time-h (Makefile.am): Substitute HAVE_TZALLOC,
+ REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z.
+ * modules/time_rz (Depends-on, configure.ac): Consider HAVE_TZALLOC,
+ REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Ignore HAVE_TIMEZONE_T.
+
* m4/strerrorname_np.m4 (gl_CHECK_STRERRORNAME_NP): Test for
strerrorname_np using gl_CHECK_FUNCS_ANDROID instead of AC_CHECK_FUNCS.
# endif
# endif
-# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@
+# if @GNULIB_TIME_RZ@
/* Functions that use a first-class time zone data type, instead of
relying on an implicit global time zone.
Inspired by NetBSD. */
/* Represents a time zone.
(timezone_t) NULL stands for UTC. */
+# if !@HAVE_TZALLOC@
+# if !GNULIB_defined_timezone_t
+# if !@HAVE_TIMEZONE_T@
typedef struct tm_zone *timezone_t;
+# else
+typedef struct tm_zone *rpl_timezone_t;
+# define timezone_t rpl_timezone_t
+# endif
+# define GNULIB_defined_timezone_t 1
+# endif
+# endif
/* tzalloc (name)
Returns a time zone object for the given time zone NAME. This object
would use it the TZ environment variable was unset.
May return NULL if NAME is invalid (this is platform dependent) or
upon memory allocation failure. */
+# if !@HAVE_TZALLOC@
_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name));
_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name));
+# endif
/* tzfree (tz)
Frees a time zone object.
The argument must have been returned by tzalloc(). */
+# if !@HAVE_TZALLOC@
_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz));
_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz));
+# endif
/* localtime_rz (tz, &t, &result)
Converts an absolute time T to a broken-down time RESULT, assuming the
time zone TZ.
This function is like 'localtime_r', but relies on the argument TZ instead
of an implicit global time zone. */
+# if @REPLACE_LOCALTIME_RZ@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef localtime_rz
+# define localtime_rz rpl_localtime_rz
+# endif
+_GL_FUNCDECL_RPL (localtime_rz, struct tm *,
+ (timezone_t __tz, time_t const *restrict __timer,
+ struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3)));
+_GL_CXXALIAS_RPL (localtime_rz, struct tm *,
+ (timezone_t __tz, time_t const *restrict __timer,
+ struct tm *restrict __result));
+# else
+# if !@HAVE_TZALLOC@
_GL_FUNCDECL_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3)));
+# endif
_GL_CXXALIAS_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result));
+# endif
/* mktime_z (tz, &tm)
Normalizes the broken-down time TM and converts it to an absolute time,
assuming the time zone TZ. Returns the absolute time.
This function is like 'mktime', but relies on the argument TZ instead
of an implicit global time zone. */
+# if @REPLACE_MKTIME_Z@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mktime_z
+# define mktime_z rpl_mktime_z
+# endif
+_GL_FUNCDECL_RPL (mktime_z, time_t,
+ (timezone_t __tz, struct tm *restrict __tm)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (mktime_z, time_t,
+ (timezone_t __tz, struct tm *restrict __tm));
+# else
+# if !@HAVE_TZALLOC@
_GL_FUNCDECL_SYS (mktime_z, time_t,
(timezone_t __tz, struct tm *restrict __tm)
_GL_ARG_NONNULL ((2)));
+# endif
_GL_CXXALIAS_SYS (mktime_z, time_t,
(timezone_t __tz, struct tm *restrict __tm));
+# endif
/* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z'
in the 'tm_zone' member of 'struct tm') are valid as long as
#include <config.h>
+/* Specification. */
#include <time.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#if NEED_TIMEZONE_NULL_SUPPORT /* Android API level >= 35 */
-#include "flexmember.h"
-#include "idx.h"
-#include "time-internal.h"
+struct tm *
+localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
+# undef localtime_rz
+{
+ if (!tz)
+ return gmtime_r (t, tm);
+ else
+ return localtime_rz (tz, t, tm);
+}
+
+time_t
+mktime_z (timezone_t tz, struct tm *tm)
+# undef mktime_z
+{
+ if (!tz)
+ return timegm (tm);
+ else
+ return mktime_z (tz, tm);
+}
+
+#else
+
+# include <errno.h>
+# include <stddef.h>
+# include <stdlib.h>
+# include <string.h>
+
+# include "flexmember.h"
+# include "idx.h"
+# include "time-internal.h"
/* The approximate size to use for small allocation requests. This is
the largest "small" request for the GNU C library malloc. */
static bool
save_abbr (timezone_t tz, struct tm *tm)
{
-#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME_ARRAY
+# if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME_ARRAY
char const *zone = NULL;
char *zone_copy = (char *) "";
-# if HAVE_TZNAME_ARRAY
+# if HAVE_TZNAME_ARRAY
int tzname_index = -1;
-# endif
+# endif
-# if HAVE_STRUCT_TM_TM_ZONE
+# if HAVE_STRUCT_TM_TM_ZONE
zone = tm->tm_zone;
-# endif
+# endif
-# if HAVE_TZNAME_ARRAY
+# if HAVE_TZNAME_ARRAY
if (! (zone && *zone) && 0 <= tm->tm_isdst)
{
tzname_index = tm->tm_isdst != 0;
zone = tzname[tzname_index];
}
-# endif
+# endif
/* No need to replace null zones, or zones within the struct tm. */
if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1)))
}
/* Replace the zone name so that its lifetime matches that of TZ. */
-# if HAVE_STRUCT_TM_TM_ZONE
+# if HAVE_STRUCT_TM_TM_ZONE
tm->tm_zone = zone_copy;
-# else
+# else
if (0 <= tzname_index)
tz->tzname_copy[tzname_index] = zone_copy;
+# endif
# endif
-#endif
return true;
}
/* Get and set the TZ environment variable. These functions can be
overridden by programs like Emacs that manage their own environment. */
-#ifndef getenv_TZ
+# ifndef getenv_TZ
static char *
getenv_TZ (void)
{
return getenv ("TZ");
}
-#endif
+# endif
-#ifndef setenv_TZ
+# ifndef setenv_TZ
static int
setenv_TZ (char const *tz)
{
return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ");
}
-#endif
+# endif
/* Change the environment to match the specified timezone_t value.
Return true if successful, false (setting errno) otherwise. */
struct tm *
localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
{
-#ifdef HAVE_LOCALTIME_INFLOOP_BUG
+# ifdef HAVE_LOCALTIME_INFLOOP_BUG
/* The -67768038400665599 comes from:
https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html
On affected platforms the greatest POSIX-compatible time_t value
errno = EOVERFLOW;
return NULL;
}
-#endif
+# endif
if (!tz)
return gmtime_r (t, tm);
return -1;
}
}
+
+#endif
# Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc.
-# serial 26
+# serial 27
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
HAVE_TIMEGM=1; AC_SUBST([HAVE_TIMEGM])
HAVE_TIMESPEC_GET=1; AC_SUBST([HAVE_TIMESPEC_GET])
HAVE_TIMESPEC_GETRES=1; AC_SUBST([HAVE_TIMESPEC_GETRES])
- dnl Even GNU libc does not have timezone_t yet.
+ dnl Even GNU libc does not have timezone_t and tzalloc() yet.
HAVE_TIMEZONE_T=0; AC_SUBST([HAVE_TIMEZONE_T])
+ HAVE_TZALLOC=0; AC_SUBST([HAVE_TZALLOC])
REPLACE_CTIME=0; AC_SUBST([REPLACE_CTIME])
REPLACE_GMTIME=0; AC_SUBST([REPLACE_GMTIME])
REPLACE_LOCALTIME=0; AC_SUBST([REPLACE_LOCALTIME])
REPLACE_LOCALTIME_R=0; AC_SUBST([REPLACE_LOCALTIME_R])
+ REPLACE_LOCALTIME_RZ=0; AC_SUBST([REPLACE_LOCALTIME_RZ])
REPLACE_MKTIME=0; AC_SUBST([REPLACE_MKTIME])
+ REPLACE_MKTIME_Z=0; AC_SUBST([REPLACE_MKTIME_Z])
REPLACE_NANOSLEEP=0; AC_SUBST([REPLACE_NANOSLEEP])
REPLACE_STRFTIME=0; AC_SUBST([REPLACE_STRFTIME])
REPLACE_TIME=0; AC_SUBST([REPLACE_TIME])
AC_DEFUN([gl_TIME_RZ],
[
- AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_REQUIRE([gl_TIME_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
# On Mac OS X 10.6, localtime loops forever with some time_t values.
# See Bug#27706, Bug#27736, and
if test "$ac_cv_type_timezone_t" = yes; then
HAVE_TIMEZONE_T=1
fi
+
+ gl_CHECK_FUNCS_ANDROID([tzalloc], [[#include <time.h>]])
+ if test $ac_cv_func_tzalloc = yes; then
+ HAVE_TZALLOC=1
+ fi
+ dnl Assume that tzalloc, localtime_rz, mktime_z are all defined together.
+ case "$gl_cv_onwards_func_tzalloc" in
+ yes)
+ case "$host_os" in
+ *-android*)
+ dnl The Android libc functions localtime_rz, mktime_z don't support
+ dnl a NULL timezone_t argument.
+ AC_DEFINE([NEED_TIMEZONE_NULL_SUPPORT], [1],
+ [Define to 1 if localtime_rz, mktime_z exist and can be used with
+ non-NULL timezone_t values.])
+ REPLACE_LOCALTIME_RZ=1
+ REPLACE_MKTIME_Z=1
+ ;;
+ esac
+ ;;
+ future*)
+ REPLACE_LOCALTIME_RZ=1
+ REPLACE_MKTIME_Z=1
+ ;;
+ esac
])
-e 's|@''HAVE_TIMESPEC_GET''@|$(HAVE_TIMESPEC_GET)|g' \
-e 's|@''HAVE_TIMESPEC_GETRES''@|$(HAVE_TIMESPEC_GETRES)|g' \
-e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
+ -e 's|@''HAVE_TZALLOC''@|$(HAVE_TZALLOC)|g' \
-e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \
-e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
-e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
-e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
+ -e 's|@''REPLACE_LOCALTIME_RZ''@|$(REPLACE_LOCALTIME_RZ)|g' \
-e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \
+ -e 's|@''REPLACE_MKTIME_Z''@|$(REPLACE_MKTIME_Z)|g' \
-e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
-e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \
-e 's|@''REPLACE_TIME''@|$(REPLACE_TIME)|g' \
extensions
time-h
tzname
-flexmember [test $HAVE_TIMEZONE_T = 0]
-idx [test $HAVE_TIMEZONE_T = 0]
-setenv [test $HAVE_TIMEZONE_T = 0]
-stdbool [test $HAVE_TIMEZONE_T = 0]
-time_r [test $HAVE_TIMEZONE_T = 0]
-timegm [test $HAVE_TIMEZONE_T = 0]
-tzset [test $HAVE_TIMEZONE_T = 0]
-unsetenv [test $HAVE_TIMEZONE_T = 0]
+flexmember [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+idx [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+setenv [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+stdbool [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+time_r [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+timegm [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+tzset [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
+unsetenv [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]
configure.ac:
gl_TIME_RZ
-gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ], [test $HAVE_TIMEZONE_T = 0])
+gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ],
+ [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1])
gl_TIME_MODULE_INDICATOR([time_rz])
Makefile.am: