From cbc0c1cda32bbcfab3ed0391cb9cfde444323571 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 8 Mar 2023 17:00:48 +0100 Subject: [PATCH] time: New module. * lib/time.in.h (time): New declaration. * lib/time.c: New file. * m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Initialize GNULIB_TIME. (gl_TIME_H_DEFAULTS): Initialize REPLACE_TIME. * m4/time.m4: New file. * modules/time-h (Makefile.am): Substitute GNULIB_TIME, REPLACE_TIME. * modules/time: New file. * tests/test-time-h-c++.cc: Check the signature of GNULIB_NAMESPACE::time. * doc/posix-functions/time.texi: Mention the glibc problem and the 'time' module. --- ChangeLog | 15 ++++++++++++ doc/posix-functions/time.texi | 10 +++++++- lib/time.c | 41 +++++++++++++++++++++++++++++++++ lib/time.in.h | 14 ++++++++++++ m4/time.m4 | 43 +++++++++++++++++++++++++++++++++++ m4/time_h.m4 | 4 +++- modules/time | 31 +++++++++++++++++++++++++ modules/time-h | 2 ++ tests/test-time-h-c++.cc | 4 ++++ 9 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 lib/time.c create mode 100644 m4/time.m4 create mode 100644 modules/time diff --git a/ChangeLog b/ChangeLog index aac31c31a5..d65b3393c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2023-03-08 Bruno Haible + + time: New module. + * lib/time.in.h (time): New declaration. + * lib/time.c: New file. + * m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Initialize GNULIB_TIME. + (gl_TIME_H_DEFAULTS): Initialize REPLACE_TIME. + * m4/time.m4: New file. + * modules/time-h (Makefile.am): Substitute GNULIB_TIME, REPLACE_TIME. + * modules/time: New file. + * tests/test-time-h-c++.cc: Check the signature of + GNULIB_NAMESPACE::time. + * doc/posix-functions/time.texi: Mention the glibc problem and the + 'time' module. + 2023-03-08 Bruno Haible time-h: Renamed from time. diff --git a/doc/posix-functions/time.texi b/doc/posix-functions/time.texi index 765de7aa2a..a8e9abcddf 100644 --- a/doc/posix-functions/time.texi +++ b/doc/posix-functions/time.texi @@ -4,10 +4,18 @@ POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html} -Gnulib module: --- +Gnulib module: time Portability problems fixed by Gnulib: @itemize +@item +This function is not consistent with @code{gettimeofday} and @code{timespec_get} +on some platforms: +@c https://sourceware.org/bugzilla/show_bug.cgi?id=30200 +glibc 2.31 or newer on Linux. +Namely, in the first 1 to 2.5 milliseconds of every second, @code{time} +returns a value that is one less than the @code{tv_sec} part of the return +value of @code{gettimeofday} or @code{timespec_get}. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/time.c b/lib/time.c new file mode 100644 index 0000000000..4e2ee31b48 --- /dev/null +++ b/lib/time.c @@ -0,0 +1,41 @@ +/* Provide time() for systems for which it's broken. + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible. */ + +#include + +/* Specification. */ +#include + +#include +#include + +time_t +time (time_t *tp) +{ + struct timeval tv; + time_t tt; + + if (gettimeofday (&tv, NULL) < 0) + abort (); + tt = tv.tv_sec; + + if (tp) + *tp = tt; + + return tt; +} diff --git a/lib/time.in.h b/lib/time.in.h index 87cda21413..3f9af920e3 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -143,6 +143,20 @@ _GL_CXXALIAS_SYS (timespec_getres, int, (struct timespec *ts, int base)); _GL_CXXALIASWARN (timespec_getres); # endif +/* Return the number of seconds that have elapsed since the Epoch. */ +# if @GNULIB_TIME@ +# if @REPLACE_TIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define time rpl_time +# endif +_GL_FUNCDECL_RPL (time, time_t, (time_t *__tp)); +_GL_CXXALIAS_RPL (time, time_t, (time_t *__tp)); +# else +_GL_CXXALIAS_SYS (time, time_t, (time_t *__tp)); +# endif +_GL_CXXALIASWARN (time); +# endif + /* Sleep for at least RQTP seconds unless interrupted, If interrupted, return -1 and store the remaining time into RMTP. See . */ diff --git a/m4/time.m4 b/m4/time.m4 new file mode 100644 index 0000000000..0dbb6011ed --- /dev/null +++ b/m4/time.m4 @@ -0,0 +1,43 @@ +# time.m4 serial 1 +dnl Copyright (C) 2023 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_FUNC_TIME], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl glibc has the bug https://sourceware.org/bugzilla/show_bug.cgi?id=30200 . + AC_CACHE_CHECK([whether time() works], + [gl_cv_func_time_works], + [dnl Guess that it works except on glibc >= 2.31 with Linux. + dnl And binaries produced on glibc < 2.31 need to run fine on newer + dnl glibc versions as well; therefore ignore __GLIBC_MINOR__. + case "$host_os" in + linux*-gnu*) + AC_EGREP_CPP([Unlucky], [ + #include + #ifdef __GNU_LIBRARY__ + #if __GLIBC__ == 2 + Unlucky GNU user + #endif + #endif + ], + [gl_cv_func_time_works="guessing no"], + [gl_cv_func_time_works="guessing yes"]) + ;; + *) gl_cv_func_time_works="guessing yes";; + esac + ]) + case "$gl_cv_func_time_works" in + *no) REPLACE_TIME=1 ;; + esac +]) + +# Prerequisites of lib/time.c. +AC_DEFUN([gl_PREREQ_TIME], +[ + : +]) diff --git a/m4/time_h.m4 b/m4/time_h.m4 index b74870c3d0..51d553a2f1 100644 --- a/m4/time_h.m4 +++ b/m4/time_h.m4 @@ -2,7 +2,7 @@ # Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc. -# serial 21 +# serial 22 # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -137,6 +137,7 @@ AC_DEFUN([gl_TIME_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_NANOSLEEP]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRFTIME]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRPTIME]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMEGM]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMESPEC_GET]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMESPEC_GETRES]) @@ -169,6 +170,7 @@ AC_DEFUN([gl_TIME_H_DEFAULTS], REPLACE_MKTIME=GNULIB_PORTCHECK; AC_SUBST([REPLACE_MKTIME]) REPLACE_NANOSLEEP=GNULIB_PORTCHECK; AC_SUBST([REPLACE_NANOSLEEP]) REPLACE_STRFTIME=GNULIB_PORTCHECK; AC_SUBST([REPLACE_STRFTIME]) + REPLACE_TIME=0; AC_SUBST([REPLACE_TIME]) REPLACE_TIMEGM=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TIMEGM]) REPLACE_TIMESPEC_GET=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TIMESPEC_GET]) REPLACE_TZSET=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TZSET]) diff --git a/modules/time b/modules/time new file mode 100644 index 0000000000..45f5ffd35f --- /dev/null +++ b/modules/time @@ -0,0 +1,31 @@ +Description: +time() function: return current time. + +Files: +lib/time.c +m4/time.m4 + +Depends-on: +time-h + +configure.ac: +gl_FUNC_TIME +gl_CONDITIONAL([GL_COND_OBJ_TIME], [test $REPLACE_TIME = 1]) +AM_COND_IF([GL_COND_OBJ_TIME], [ + gl_PREREQ_TIME +]) +gl_TIME_MODULE_INDICATOR([time]) + +Makefile.am: +if GL_COND_OBJ_TIME +lib_SOURCES += time.c +endif + +Include: + + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/time-h b/modules/time-h index 75ff3a4d8c..5b0fc3feae 100644 --- a/modules/time-h +++ b/modules/time-h @@ -38,6 +38,7 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ -e 's/@''GNULIB_STRFTIME''@/$(GNULIB_STRFTIME)/g' \ -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ + -e 's/@''GNULIB_TIME''@/$(GNULIB_TIME)/g' \ -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ -e 's/@''GNULIB_TIMESPEC_GET''@/$(GNULIB_TIMESPEC_GET)/g' \ -e 's/@''GNULIB_TIMESPEC_GETRES''@/$(GNULIB_TIMESPEC_GETRES)/g' \ @@ -59,6 +60,7 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ + -e 's|@''REPLACE_TIME''@|$(REPLACE_TIME)|g' \ -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ -e 's|@''REPLACE_TIMESPEC_GET''@|$(REPLACE_TIMESPEC_GET)|g' \ -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \ diff --git a/tests/test-time-h-c++.cc b/tests/test-time-h-c++.cc index 70b2a0f0c7..13cb436e1b 100644 --- a/tests/test-time-h-c++.cc +++ b/tests/test-time-h-c++.cc @@ -28,6 +28,10 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::timespec_get, int, (struct timespec *, int)); #endif +#if GNULIB_TEST_TIME +SIGNATURE_CHECK (GNULIB_NAMESPACE::time, time_t, (time_t *)); +#endif + #if GNULIB_TEST_NANOSLEEP SIGNATURE_CHECK (GNULIB_NAMESPACE::nanosleep, int, (struct timespec const *, struct timespec *)); -- 2.39.5