configure output from largefile.m4

2024-06-16 Thread Bruno Haible
Hi Paul,

In a configure output I see:

  checking for -I/Users/runner/include -I/usr/local/opt/libiconv/include -Wall 
-DCONTINUE_AFTER_ASSERT option for large files... none needed
  checking for -I/Users/runner/include -I/usr/local/opt/libiconv/include -Wall 
-DCONTINUE_AFTER_ASSERT option for timestamps after 2038... none needed

It comes from largefile.m4:

  AC_CACHE_CHECK([for $CPPFLAGS option for large files],

and

  AC_CACHE_CHECK([for $CPPFLAGS option for timestamps after 2038],

Printing the CPPFLAGS makes no sense to me. I understand that for
some configure tests, we write

  checking for gcc option ... ...

but since in this case the options are independent of the compiler
and even independent of C vs. C++ mode, it would be adequate to print

  checking for compiler option for large files... none needed
  checking for compiler option for timestamps after 2038... none needed

Right?

Also, as mentioned in [1], I find the wording
  option to enable large file support
more understandable than
  option for large files

Bruno

[1] https://lists.gnu.org/archive/html/bug-gnulib/2024-04/msg00420.html






[PATCH 0/7] avoiding tzname usage in Gnulib code

2024-06-16 Thread Paul Eggert
tzname is problematic, because (as now mentioned in the Gnulib manual)
it's unsafe in multithreaded code and its contents are typically
unspecified even in single-threaded code.  These patches rework
the Gnulib code so that no other module depends on tzname.

Paul Eggert (7):
  nstrftime: rename HAVE_TM_GMTOFF
  time_r-tests: avoid tzname test
  time: document struct tm portability
  time_r: refactor tm_zone tests
  parse-datetime: don’t depend on tzname
  nstrftime,time_rz: don’t depend on tzname
  nstrftime: omit never-used code

 ChangeLog   |  57 +++
 doc/posix-headers/time.texi |  15 
 lib/parse-datetime.y| 123 ---
 lib/strftime.c  | 141 ++--
 lib/strptime.c  |   2 +-
 lib/time-internal.h |  21 --
 lib/time_rz.c   |  45 ++--
 m4/tm_gmtoff.m4 |  26 +--
 modules/c-nstrftime |   3 +-
 modules/nstrftime   |   3 +-
 modules/parse-datetime  |   3 +-
 modules/time_r-tests|   6 +-
 modules/time_rz |   1 -
 tests/test-parse-datetime.c |   6 +-
 14 files changed, 257 insertions(+), 195 deletions(-)

--
2.43.0




[PATCH 4/7] time_r: refactor tm_zone tests

2024-06-16 Thread Paul Eggert
* m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Also check for tm_zone
and define HAVE_STRUCT_TM_TM_ZONE accordingly.
* modules/time_r-tests (Files): Add m4/tm_gmtoff.m4.
(configure.ac): Simplify by using gl_TM_GMTOFF.
---
 ChangeLog|  6 ++
 m4/tm_gmtoff.m4  | 13 +++--
 modules/time_r-tests |  5 ++---
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 54eeb40706..5c24caebca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2024-06-16  Paul Eggert  
 
+   time_r: refactor tm_zone tests
+   * m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Also check for tm_zone
+   and define HAVE_STRUCT_TM_TM_ZONE accordingly.
+   * modules/time_r-tests (Files): Add m4/tm_gmtoff.m4.
+   (configure.ac): Simplify by using gl_TM_GMTOFF.
+
time_r-tests: avoid tzname test
* modules/time_r-tests (configure.ac):
Do not check for tzname, as the tests don’t use it.
diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4
index ad64df4954..3d97edb7a7 100644
--- a/m4/tm_gmtoff.m4
+++ b/m4/tm_gmtoff.m4
@@ -1,13 +1,22 @@
 # tm_gmtoff.m4
-# serial 4
+# serial 5
 dnl Copyright (C) 2002, 2009-2024 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 Check for tm_gmtoff and tm_zone in struct tm, and #define
+dnl HAVE_STRUCT_TM_TM_GMTOFF and HAVE_STRUCT_TM_TM_ZONE accordingly.
+dnl Most code that needs one needs the other, so there seemed little
+dnl point to having two macros to check them individually.
+dnl Although all platforms that we know of have either both members or
+dnl neither member, check for the two members separately just in case.
+dnl
+dnl These days this macro is more useful than AC_STRUCT_TIMEZONE, which also
+dnl checks for the obsolescent tzname and does not check for tm_gmtoff.
 AC_DEFUN([gl_TM_GMTOFF],
 [
-  AC_CHECK_MEMBERS([struct tm.tm_gmtoff], [], [],
+  AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [],
 [[#include 
 ]])
 
diff --git a/modules/time_r-tests b/modules/time_r-tests
index 9d82cb3657..c29d09cc24 100644
--- a/modules/time_r-tests
+++ b/modules/time_r-tests
@@ -1,4 +1,5 @@
 Files:
+m4/tm_gmtoff.m4
 tests/test-gmtime_r.c
 tests/test-gmtime_r-mt.c
 tests/test-localtime_r.c
@@ -11,9 +12,7 @@ thread
 nanosleep
 
 configure.ac:
-AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [],
-  [[#include 
-  ]])
+gl_TM_GMTOFF
 
 Makefile.am:
 TESTS += \
-- 
2.43.0




[PATCH 5/7] parse-datetime: don’t depend on tzname

2024-06-16 Thread Paul Eggert
* lib/parse-datetime.y (TIME_ZONE_BUFSIZE): Move earlier.
(parser_control) [!HAVE_STRUCT_TM_TM_ZONE]:
New member tz_abbr, to save abbrs calculated by strftime %Z.
(populate_local_time_zone_table): New function, which
optimizes the HAVE_STRUCT_TM_TM_ZONE case as before,
and falls back on strftime with %Z otherwise.
Although strftime %Z can be more accurate than the old tzname
based method, the new heuristic is still wrong so often that it
probably doesn’t help all that much.
(parse_datetime_body): Use it.
* modules/parse-datetime (Depends-on): Remove tzname.
---
 ChangeLog  |  13 +
 lib/parse-datetime.y   | 115 ++---
 modules/parse-datetime |   3 +-
 3 files changed, 76 insertions(+), 55 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5c24caebca..d956d9a046 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2024-06-16  Paul Eggert  
 
+   parse-datetime: don’t depend on tzname
+   * lib/parse-datetime.y (TIME_ZONE_BUFSIZE): Move earlier.
+   (parser_control) [!HAVE_STRUCT_TM_TM_ZONE]:
+   New member tz_abbr, to save abbrs calculated by strftime %Z.
+   (populate_local_time_zone_table): New function, which
+   optimizes the HAVE_STRUCT_TM_TM_ZONE case as before,
+   and falls back on strftime with %Z otherwise.
+   Although strftime %Z can be more accurate than the old tzname
+   based method, the new heuristic is still wrong so often that it
+   probably doesn’t help all that much.
+   (parse_datetime_body): Use it.
+   * modules/parse-datetime (Depends-on): Remove tzname.
+
time_r: refactor tm_zone tests
* m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Also check for tm_zone
and define HAVE_STRUCT_TM_TM_ZONE accordingly.
diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y
index f98e7200d6..665401d422 100644
--- a/lib/parse-datetime.y
+++ b/lib/parse-datetime.y
@@ -144,6 +144,9 @@ typedef struct
 /* Meridian: am, pm, or 24-hour style.  */
 enum { MERam, MERpm, MER24 };
 
+/* Maximum length of a time zone abbreviation, plus 1.  */
+enum { TIME_ZONE_BUFSIZE = INT_STRLEN_BOUND (intmax_t) + sizeof ":MM:SS" };
+
 /* A reasonable upper bound for the buffer used in debug output.  */
 enum { DBGBUFSIZE = 100 };
 
@@ -230,6 +233,11 @@ typedef struct
 
   /* Table of local time zone abbreviations, terminated by a null entry.  */
   table local_time_zone_table[3];
+
+#if !HAVE_STRUCT_TM_TM_ZONE
+  /* The abbreviations in LOCAL_TIME_ZONE_TABLE.  */
+  char tz_abbr[2][TIME_ZONE_BUFSIZE];
+#endif
 } parser_control;
 
 static bool
@@ -386,8 +394,6 @@ str_days (parser_control *pc, char *buffer, int n)
 
 /* Convert a time zone to its string representation.  */
 
-enum { TIME_ZONE_BUFSIZE = INT_STRLEN_BOUND (intmax_t) + sizeof ":MM:SS" } ;
-
 static char const *
 time_zone_str (int time_zone, char time_zone_buf[TIME_ZONE_BUFSIZE])
 {
@@ -1565,6 +1571,33 @@ mktime_ok (struct tm const *tm0, struct tm const *tm1)
 | (tm0->tm_year ^ tm1->tm_year));
 }
 
+/* Populate PC's local time zone table with information from TM.  */
+
+static void
+populate_local_time_zone_table (parser_control *pc, struct tm const *tm)
+{
+  bool first_entry_exists = !!pc->local_time_zone_table[0].name;
+
+  /* The table entry to be filled in.  There are only two, so this is
+ the first entry if it is missing, the second entry otherwise.  */
+  table *e = &pc->local_time_zone_table[first_entry_exists];
+
+  e->type = tLOCAL_ZONE;
+  e->value = tm->tm_isdst;
+
+  char const *zone = NULL;
+#if HAVE_STRUCT_TM_TM_ZONE
+  if (tm->tm_zone[0])
+zone = tm->tm_zone;
+#else
+  char *tz_abbr = pc->tz_abbr[first_entry_exists];
+  if (nstrftime (tz_abbr, TIME_ZONE_BUFSIZE, "%Z", tm, 0, 0))
+zone = tz_abbr;
+#endif
+  e->name = zone;
+  e[1].name = NULL;
+}
+
 /* Debugging: format a 'struct tm' into a buffer, taking the parser's
timezone information into account (if pc != NULL).  */
 static char const *
@@ -1833,61 +1866,37 @@ parse_datetime_body (struct timespec *result, char 
const *p,
   pc.debug_year_seen = false;
   pc.debug_ordinal_day_seen = false;
 
-#if HAVE_STRUCT_TM_TM_ZONE
-  pc.local_time_zone_table[0].name = tmp.tm_zone;
-  pc.local_time_zone_table[0].type = tLOCAL_ZONE;
-  pc.local_time_zone_table[0].value = tmp.tm_isdst;
-  pc.local_time_zone_table[1].name = NULL;
+  pc.local_time_zone_table[0].name = NULL;
+  populate_local_time_zone_table (&pc, &tmp);
 
   /* Probe the names used in the next three calendar quarters, looking
  for a tm_isdst different from the one we already have.  */
-  {
-int quarter;
-for (quarter = 1; quarter <= 3; quarter++)
-  {
-time_t probe;
-if (ckd_add (&probe, Start, quarter * (90 * 24 * 60 * 60)))
-  break;
-struct tm probe_tm;
-if (localtime_rz (tz, &probe, &probe_tm) && probe_tm.tm_zone
-&& probe_tm.tm_isdst != pc.local_time_zone_table[0].value)
-  {
-  {
-pc.local_t

[PATCH 6/7] nstrftime, time_rz: don’t depend on tzname

2024-06-16 Thread Paul Eggert
* lib/strftime.c (HAVE_TZNAME_ARRAY) [_LIBC]: Remove.
All uses removed.
(__strftime_internal): Simplify calculation of zone to be closer
to what glibc does.  However, in Gnulib do not look at tzname as
this is problematic for all the usual reasons; instead, use the
underlying strftime with %Z, making sure that call to the
underlying strftime is now always compiled in the non-glibc case.
Set and revert TZ as needed around the underlying call.
* lib/time-internal.h (struct tm_zone)
[HAVE_TZNAME_ARRAY && !HAVE_STRUCT_TM_TM_ZONE]: Remove tzname_copy.
All uses removed.
(set_tz, revert_tz): Declare, as they’re now extern.
(local_tz): Move here from time_rz.c, and now a macro.
* lib/time_rz.c (save_abbr): Do not worry about tzname_copy,
since strftime.c no longer needs it.  Instead, save abbrs
only from tm_zone.
* modules/c-nstrftime, modules/nstrftime, modules/time_rz:
(Depends-on): Remove tzname.
---
 ChangeLog   |  20 +++
 lib/strftime.c  | 123 
 lib/time-internal.h |  21 +---
 lib/time_rz.c   |  45 +++-
 modules/c-nstrftime |   3 +-
 modules/nstrftime   |   3 +-
 modules/time_rz |   1 -
 7 files changed, 108 insertions(+), 108 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d956d9a046..b93e4b0c32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2024-06-16  Paul Eggert  
 
+   nstrftime,time_rz: don’t depend on tzname
+   * lib/strftime.c (HAVE_TZNAME_ARRAY) [_LIBC]: Remove.
+   All uses removed.
+   (__strftime_internal): Simplify calculation of zone to be closer
+   to what glibc does.  However, in Gnulib do not look at tzname as
+   this is problematic for all the usual reasons; instead, use the
+   underlying strftime with %Z, making sure that call to the
+   underlying strftime is now always compiled in the non-glibc case.
+   Set and revert TZ as needed around the underlying call.
+   * lib/time-internal.h (struct tm_zone)
+   [HAVE_TZNAME_ARRAY && !HAVE_STRUCT_TM_TM_ZONE]: Remove tzname_copy.
+   All uses removed.
+   (set_tz, revert_tz): Declare, as they’re now extern.
+   (local_tz): Move here from time_rz.c, and now a macro.
+   * lib/time_rz.c (save_abbr): Do not worry about tzname_copy,
+   since strftime.c no longer needs it.  Instead, save abbrs
+   only from tm_zone.
+   * modules/c-nstrftime, modules/nstrftime, modules/time_rz:
+   (Depends-on): Remove tzname.
+
parse-datetime: don’t depend on tzname
* lib/parse-datetime.y (TIME_ZONE_BUFSIZE): Move earlier.
(parser_control) [!HAVE_STRUCT_TM_TM_ZONE]:
diff --git a/lib/strftime.c b/lib/strftime.c
index cd216fb6a5..6688c90e11 100644
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -27,7 +27,6 @@
 # define HAVE_STRUCT_ERA_ENTRY 1
 # define HAVE_STRUCT_TM_TM_GMTOFF 1
 # define HAVE_STRUCT_TM_TM_ZONE 1
-# define HAVE_TZNAME_ARRAY 1
 # include "../locale/localeinfo.h"
 #else
 # include 
@@ -809,9 +808,9 @@ static CHAR_T const c_month_names[][sizeof "September"] =
 #endif
 
 
-/* When compiling this file, GNU applications can #define my_strftime
-   to a symbol (typically nstrftime) to get an extended strftime with
-   extra arguments TZ and NS.  */
+/* When compiling this file, Gnulib-using applications should #define
+   my_strftime to a symbol (typically nstrftime) to name their
+   extended strftime with extra arguments TZ and NS.  */
 
 #ifdef my_strftime
 # define extra_args , tz, ns
@@ -925,9 +924,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
 /* The English AM/PM strings happen to have the same length, namely 2.  */
 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
 # define ap_len 2
-#endif
-#if HAVE_TZNAME_ARRAY
-  char **tzname_vec = tzname;
 #endif
   const char *zone;
   size_t i = 0;
@@ -946,37 +942,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
  This is bogus: though POSIX allows bad behavior like this,
  POSIX does not require it.  Do the right thing instead.  */
   zone = (const char *) tp->tm_zone;
-#endif
-#if HAVE_TZNAME_ARRAY
+#else
   if (!tz)
 {
   if (! (zone && *zone))
 zone = "GMT";
 }
-  else
-{
-# if !HAVE_STRUCT_TM_TM_ZONE
-  /* Infer the zone name from *TZ instead of from TZNAME.  */
-  tzname_vec = tz->tzname_copy;
-# endif
-}
-  /* The tzset() call might have changed the value.  */
-  if (!(zone && *zone) && tp->tm_isdst >= 0)
-{
-  /* POSIX.1 requires that local time zone information be used as
- though strftime called tzset.  */
-# ifndef my_strftime
-  if (!*tzset_called)
-{
-  tzset ();
-  *tzset_called = true;
-}
-# endif
-  zone = tzname_vec[tp->tm_isdst != 0];
-}
 #endif
-  if (! zone)
-zone = "";
 
   if (hour12 > 12)
 hour12 -= 12;
@@ -1007,6 +979,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
   bool change_c

[PATCH 2/7] time_r-tests: avoid tzname test

2024-06-16 Thread Paul Eggert
* modules/time_r-tests (configure.ac):
Do not check for tzname, as the tests don’t use it.
Simply check for struct tm.tm_zone.
---
 ChangeLog| 5 +
 modules/time_r-tests | 7 +++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ebdd04567f..54eeb40706 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2024-06-16  Paul Eggert  
 
+   time_r-tests: avoid tzname test
+   * modules/time_r-tests (configure.ac):
+   Do not check for tzname, as the tests don’t use it.
+   Simply check for struct tm.tm_zone.
+
nstrftime: rename HAVE_TM_GMTOFF
* m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Rename HAVE_TM_GMTOFF
to HAVE_STRUCT_TM_TM_GMTOFF, for consistency with
diff --git a/modules/time_r-tests b/modules/time_r-tests
index 56346c0f7c..9d82cb3657 100644
--- a/modules/time_r-tests
+++ b/modules/time_r-tests
@@ -11,10 +11,9 @@ thread
 nanosleep
 
 configure.ac:
-dnl Possibly define HAVE_STRUCT_TM_TM_ZONE.
-AC_REQUIRE([AC_STRUCT_TIMEZONE])
-dnl Possibly define HAVE_STRUCT_TM_TM_GMTOFF.
-AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include ]])
+AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [],
+  [[#include 
+  ]])
 
 Makefile.am:
 TESTS += \
-- 
2.43.0




[PATCH 3/7] time: document struct tm portability

2024-06-16 Thread Paul Eggert
* doc/posix-headers/time.texi: Mention issues with tm_gmtoff,
tm_zone, tzname, etc.
---
 doc/posix-headers/time.texi | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/doc/posix-headers/time.texi b/doc/posix-headers/time.texi
index e7304cbd1a..26587d4c6a 100644
--- a/doc/posix-headers/time.texi
+++ b/doc/posix-headers/time.texi
@@ -30,7 +30,22 @@ glibc 2.34+ atop 32-bit x86 or ARM Linux.
 @end itemize
 
 Portability problems not fixed by Gnulib:
+
 @itemize
+@item
+On some platforms @code{struct tm} lacks the the @code{tm_gmtoff} and
+@code{tm_zone} members:
+AIX 7.3, HP-UX 11, Solaris 11.4, mingw, MSVC 14.
+
+@item
+On some platforms the global state variables @code{daylight},
+@code{timezone} and @code{tzname} are not available.  Even on
+platforms where they are available, their contents are often unreliable,
+even in single-threaded programs.
+Portable code can instead use @code{struct tm}'s @code{tm_gmtoff} and
+@code{tm_zone} members when available, and the @code{strftime} function
+with @code{%z} or @code{%Z} conversion specifiers otherwise.
+
 @item
 On platforms where @code{time_t} is always 32-bit, functions like
 @code{stat} can fail with @code{errno == EOVERFLOW} when a timestamp
-- 
2.43.0




[PATCH] Fix typos in ChangeLog and getpagesize.texi

2024-06-16 Thread Paul Eggert
---
 ChangeLog| 2 +-
 doc/glibc-functions/getpagesize.texi | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c07a4b757a..3f5d7454fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,7 +58,7 @@
xsize: port to SIZE_MAX <= INT_MAX
* lib/xsize.h (xsum): Port to oddball platforms where SIZE_MAX <=
INT_MAX.  Although no such platform is a current Gnulib porting
-   problems, it’s easy enough to port to them.
+   target, it’s easy enough to port to them.
 
ssfmalloc-tests: simplify by using sysconf
* tests/test-ssfmalloc.c (getpagesize) [__hpux]: Remove decl.
diff --git a/doc/glibc-functions/getpagesize.texi 
b/doc/glibc-functions/getpagesize.texi
index 77df489bce..3c60942742 100644
--- a/doc/glibc-functions/getpagesize.texi
+++ b/doc/glibc-functions/getpagesize.texi
@@ -42,7 +42,7 @@ Although portable programs are supposed to use @code{sysconf 
(_SC_PAGESIZE)}
 instead, in practice @code{getpagesize} can be a little faster.
 
 @item
-On typical platforms this function's API limits page sizes to at most 1 GiB@,
+On typical platforms this function's API limits page sizes to at most 1 GiB,
 even though @code{sysconf (_SC_PAGESIZE)} does not have this limitation.
 However, this has not been a practical problem yet,
 and so many programs use @code{getpagesize} that it's unlikely that
-- 
2.43.0




[PATCH 7/7] nstrftime: omit never-used code

2024-06-16 Thread Paul Eggert
* lib/strftime.c (__strftime_internal): Remove code protected by
‘#ifndef my_strftime’.  my_strftime is always defined.  This
code isn’t needed for POSIX conformance as it’s never used in glibc.
---
 ChangeLog  |  6 ++
 lib/strftime.c | 10 --
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b93e4b0c32..52c07bde4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2024-06-16  Paul Eggert  
 
+   nstrftime: omit never-used code
+   * lib/strftime.c (__strftime_internal): Remove code protected by
+   ‘#ifndef my_strftime’.  my_strftime is always defined.  This
+   code isn’t needed for POSIX conformance as it’s never used in glibc.
+
nstrftime,time_rz: don’t depend on tzname
* lib/strftime.c (HAVE_TZNAME_ARRAY) [_LIBC]: Remove.
All uses removed.
@@ -9,6 +14,7 @@
underlying strftime with %Z, making sure that call to the
underlying strftime is now always compiled in the non-glibc case.
Set and revert TZ as needed around the underlying call.
+
* lib/time-internal.h (struct tm_zone)
[HAVE_TZNAME_ARRAY && !HAVE_STRUCT_TM_TM_ZONE]: Remove tzname_copy.
All uses removed.
diff --git a/lib/strftime.c b/lib/strftime.c
index 6688c90e11..e33dbb8f7c 100644
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -2020,16 +2020,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
 struct tm ltm;
 time_t lt;
 
-/* POSIX.1 requires that local time zone information be used as
-   though strftime called tzset.  */
-# ifndef my_strftime
-if (!*tzset_called)
-  {
-tzset ();
-*tzset_called = true;
-  }
-# endif
-
 ltm = *tp;
 ltm.tm_wday = -1;
 lt = mktime_z (tz, 

[PATCH 1/7] nstrftime: rename HAVE_TM_GMTOFF

2024-06-16 Thread Paul Eggert
* m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Rename HAVE_TM_GMTOFF
to HAVE_STRUCT_TM_TM_GMTOFF, for consistency with
HAVE_STRUCT_TM_TM_ZONE.  All uses changed.
---
 ChangeLog   |  7 +++
 lib/parse-datetime.y|  8 
 lib/strftime.c  |  8 
 lib/strptime.c  |  2 +-
 m4/tm_gmtoff.m4 | 17 +++--
 tests/test-parse-datetime.c |  6 +++---
 6 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b551084953..ebdd04567f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-06-16  Paul Eggert  
+
+   nstrftime: rename HAVE_TM_GMTOFF
+   * m4/tm_gmtoff.m4 (gl_TM_GMTOFF): Rename HAVE_TM_GMTOFF
+   to HAVE_STRUCT_TM_TM_GMTOFF, for consistency with
+   HAVE_STRUCT_TM_TM_ZONE.  All uses changed.
+
 2024-06-15  Bruno Haible  
 
Drop outdated cppi configuration.
diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y
index 83e0ba38ce..f98e7200d6 100644
--- a/lib/parse-datetime.y
+++ b/lib/parse-datetime.y
@@ -1311,7 +1311,7 @@ lookup_zone (parser_control const *pc, char const *name)
   return NULL;
 }
 
-#if ! HAVE_TM_GMTOFF
+#if ! HAVE_STRUCT_TM_TM_GMTOFF
 /* Yield the difference between *A and *B,
measured in seconds, ignoring leap seconds.
The body of this function is taken directly from the GNU C Library;
@@ -1336,7 +1336,7 @@ tm_diff (const struct tm *a, const struct tm *b)
 + (a->tm_min - b->tm_min))
   + (a->tm_sec - b->tm_sec));
 }
-#endif /* ! HAVE_TM_GMTOFF */
+#endif
 
 static table const *
 lookup_word (parser_control const *pc, char *word)
@@ -2221,7 +2221,7 @@ parse_datetime_body (struct timespec *result, char const 
*p,
   if (pc.zones_seen)
 {
   bool overflow = false;
-#ifdef HAVE_TM_GMTOFF
+#ifdef HAVE_STRUCT_TM_TM_GMTOFF
   long int utcoff = tm.tm_gmtoff;
 #else
   time_t t = Start;
@@ -2337,7 +2337,7 @@ parse_datetime_body (struct timespec *result, char const 
*p,
 dbg_tm, sizeof dbg_tm));
   if (localtime_rz (tz, &result->tv_sec, &lmt))
 {
-#ifdef HAVE_TM_GMTOFF
+#ifdef HAVE_STRUCT_TM_TM_GMTOFF
   bool got_utcoff = true;
   long int utcoff = lmt.tm_gmtoff;
 #else
diff --git a/lib/strftime.c b/lib/strftime.c
index 7d124e68f3..cd216fb6a5 100644
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -25,7 +25,7 @@
 #ifdef _LIBC
 # define USE_IN_EXTENDED_LOCALE_MODEL 1
 # define HAVE_STRUCT_ERA_ENTRY 1
-# define HAVE_TM_GMTOFF 1
+# define HAVE_STRUCT_TM_TM_GMTOFF 1
 # define HAVE_STRUCT_TM_TM_ZONE 1
 # define HAVE_TZNAME_ARRAY 1
 # include "../locale/localeinfo.h"
@@ -746,7 +746,7 @@ should_remove_ampm (void)
 #endif
 
 
-#if ! HAVE_TM_GMTOFF
+#if ! HAVE_STRUCT_TM_TM_GMTOFF
 /* Yield the difference between *A and *B,
measured in seconds, ignoring leap seconds.  */
 # define tm_diff ftime_tm_diff
@@ -771,7 +771,7 @@ tm_diff (const struct tm *a, const struct tm *b)
 + (a->tm_min - b->tm_min))
   + (a->tm_sec - b->tm_sec));
 }
-#endif /* ! HAVE_TM_GMTOFF */
+#endif
 
 
 
@@ -1998,7 +1998,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
 int hour_diff;
 int min_diff;
 int sec_diff;
-#if HAVE_TM_GMTOFF
+#if HAVE_STRUCT_TM_TM_GMTOFF
 diff = tp->tm_gmtoff;
 #else
 if (!tz)
diff --git a/lib/strptime.c b/lib/strptime.c
index 568caf6df8..e0fe2bfd9a 100644
--- a/lib/strptime.c
+++ b/lib/strptime.c
@@ -713,7 +713,7 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt 
LOCALE_PARAM)
   }
 if (val > 1200)
   return NULL;
-#if defined _LIBC || HAVE_TM_GMTOFF
+#if defined _LIBC || HAVE_STRUCT_TM_TM_GMTOFF
 tm->tm_gmtoff = (val * 3600) / 100;
 if (neg)
   tm->tm_gmtoff = -tm->tm_gmtoff;
diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4
index 0c7dcb2a09..ad64df4954 100644
--- a/m4/tm_gmtoff.m4
+++ b/m4/tm_gmtoff.m4
@@ -1,5 +1,5 @@
 # tm_gmtoff.m4
-# serial 3
+# serial 4
 dnl Copyright (C) 2002, 2009-2024 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,9 +7,14 @@ dnl with or without modifications, as long as this notice is 
preserved.
 
 AC_DEFUN([gl_TM_GMTOFF],
 [
- AC_CHECK_MEMBER([struct tm.tm_gmtoff],
- [AC_DEFINE([HAVE_TM_GMTOFF], [1],
-[Define if struct tm has the tm_gmtoff member.])],
- ,
- [#include ])
+  AC_CHECK_MEMBERS([struct tm.tm_gmtoff], [], [],
+[[#include 
+]])
+
+  dnl Backward compatibility with 2024-and-earlier versions of this macro.
+  AS_IF([test "$ac_cv_member_struct_tm_tm_gmtoff" = yes],
+[AC_DEFINE([HAVE_TM_GMTOFF], [1],
+   [Define if struct tm has the tm_gmtoff member.
+This macro is obsolete.
+New code should use HAVE_STRUCT_TM_T

Re: new module 'tzname', tm_zone and tm_gmtoff

2024-06-16 Thread Paul Eggert

On 2024-06-06 14:30, Bruno Haible wrote:

OK. But how about the Linux man-pages?

   *https://man7.org/linux/man-pages/man3/tzset.3p.html
 is derived from POSIX and will be updated forPOSIX:2024, but
 POSIX:2024  (p. 2310-2311) does not warn against these 3 variables.

   *https://man7.org/linux/man-pages/man3/tzset.3.html
 does not warn against these 3 variables either.

   *https://man7.org/linux/man-pages/man3/tm.3type.html
 says that "The tm_gmtoff field provides an alternative"
 for systems without the 'timezone' variable. (Yes! Not the
 other way around.)

Will you also write tolinux-...@vger.kernel.org  ?


Done, and it's been fixed in man-pages 6.9, which now says this in 
tzset.3 in a new CAVEATS section:


"Because the values of tzname, timezone, and daylight are often 
unspecified, and accessing them can lead to undefined behavior in 
multithreaded applications, code should instead obtain time zone offset 
and abbreviations from the tm_gmtoff and tm_zone members of the 
broken-down time structure tm(3type)."


I didn't see a need to update tm(3type), since this is in its VERSIONS 
section which is talking about ancient history, but if you can see for 
some improved wording there please feel free to follow up.


I added similar wording to the tzcode man pages, and this should appear 
in the next TZDB release:


https://github.com/eggert/tz/commit/03fd9e45197e546652933981fc563267c2a0bb5b

I also updated the glibc manual to contain similar wording, and these 
changes should appear in the next glibc release:


https://github.com/bminor/glibc/commit/ee768a30fe9099972dad04c49972c2508a208b9b




Re: new module 'tzname', tm_zone and tm_gmtoff

2024-06-16 Thread Paul Eggert

On 2024-06-06 17:03, Bruno Haible wrote:

Paul Eggert wrote:

tzname is used in three places:
- time_rz,


This should be fixed to use strftime instead.


This seems wrong for two reasons:

   * time_rz is a small module, without textual I/O.


Fair enough, and the changes I recently installed into Gnulib solved 
this problem in a different way, which make time_rz even smaller. As you 
suggested, the updated time_rz does not use strftime.




   * It is bad design to require calling a complicated function
 in order to get elementary data about something.


True, but unfortunately strftime %Z is the only widely supported and 
portable way to get the time zone abbreviation.


In the long run I suppose we can assume struct tm's tm_zone instead. But 
this is standardized only in POSIX.1-2024, and for many years apps will 
need to deal with less-capable systems, notably Microsoft Windows.


We could create a new module to get a time zone abbreviation. It could 
define a new function that is given BUF, SIZE, TM and TZ and would be 
the equivalent of strftime (BUF, SIZE, "%Z", TM) in the timezone TZ, and 
tuned for the common case where TM->tm_zone exists. Offhand I know of 
only one program that could use this function: GNU Emacs (which 
currently just does strftime and doesn't bother tuning for tm_zone), but 
if there are others then such a module might be worth writing.


Regardless of whether we add such a module, though, we should remove the 
tzname module from Gnulib, as Gnulib doesn't need it any more and nobody 
should use it. Proposed patch attached.




> >- parse-datetime,
> 
> Likewise.  (This usage of tzname is simply wrong, by the way, but it can 
> be compatibly wrong.)


That would require two (!) strftime calls, one to get the time zone
without DST abbrev, and one to get the time zone with DST abbrev. This is
gross.


Although strftime may be gross it's more portable than tzname, and more 
reliable than tzname even on platforms that have tzname.


Also, parse-datetime.y is not a good argument for the utility of tzname 
as it has an incorrect model for how time zone abbreviations work. It 
ignores the recommendation in 
 that says, 
"Alphabetic time zone abbreviations should not be used as unique 
identifiers for UT offsets as they are ambiguous in practice." And it 
doesn't even ignore the recommendation correctly, as it wrongly assumes 
that there are at most two time zone abbreviations for any particular 
time zone setting. We shouldn't rely on parse-datetime.y for insight as 
to what primitives Gnulib should be supporting in this area.From 668e8c9f0ea08a273797507f29179de419f155f3 Mon Sep 17 00:00:00 2001
From: Paul Eggert 
Date: Sun, 16 Jun 2024 16:34:03 -0700
Subject: [PATCH] tzname: remove module

This recently-introduced module was used only internally by Gnulib,
and as all uses have been removed the module can be removed.
As discussed in the Gnulib manual, tzname is problematic
and GNU programs should generally avoid it.
* MODULES.html.sh, NEWS, doc/posix-functions/tzname.texi:
Adjust to module removal.
* lib/time.in.h tzname [@GNULIB_TZNAME@ && NEED_DECL_TZNAME]:
Remove decl and macro.
* m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Remove GNULIB_TZNAME.
* m4/tzname.m4, modules/tzname, modules/tzname-tests:
* tests/test-tzname.c: Remove.
* modules/time-h (time.h): Do not substitute GNULIB_TZNAME.
---
 ChangeLog   | 14 
 MODULES.html.sh |  1 -
 NEWS|  3 ++
 doc/posix-functions/tzname.texi |  9 ++---
 lib/time.in.h   | 17 -
 m4/time_h.m4|  3 +-
 m4/tzname.m4| 62 -
 modules/time-h  |  1 -
 modules/tzname  | 23 
 modules/tzname-tests| 11 --
 tests/test-tzname.c | 36 ---
 11 files changed, 23 insertions(+), 157 deletions(-)
 delete mode 100644 m4/tzname.m4
 delete mode 100644 modules/tzname
 delete mode 100644 modules/tzname-tests
 delete mode 100644 tests/test-tzname.c

diff --git a/ChangeLog b/ChangeLog
index 52c07bde4f..6907435460 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2024-06-16  Paul Eggert  
 
+	tzname: remove module
+	This recently-introduced module was used only internally by Gnulib,
+	and as all uses have been removed the module can be removed.
+	As discussed in the Gnulib manual, tzname is problematic
+	and GNU programs should generally avoid it.
+	* MODULES.html.sh, NEWS, doc/posix-functions/tzname.texi:
+	Adjust to module removal.
+	* lib/time.in.h tzname [@GNULIB_TZNAME@ && NEED_DECL_TZNAME]:
+	Remove decl and macro.
+	* m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Remove GNULIB_TZNAME.
+	* m4/tzname.m4, modules/tzname, modules/tzname-tests:
+	* tests/test-tzname.c: Remove.
+	* modules/time-h (time.h): Do not substitute GNULIB_TZNAME.
+
 	nstrftime:

[PATCH] useless-if-before-free: Check for nullptr.

2024-06-16 Thread Collin Funk
* build-aux/useless-if-before-free (is_NULL): Add nullptr to the
condition.
(foo): Add nullptr to the regular expressions.
---
 ChangeLog| 7 +++
 build-aux/useless-if-before-free | 8 
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 52c07bde4f..7cff764b38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-06-16  Collin Funk  
+
+   useless-if-before-free: Check for nullptr.
+   * build-aux/useless-if-before-free (is_NULL): Add nullptr to the
+   condition.
+   (foo): Add nullptr to the regular expressions.
+
 2024-06-16  Paul Eggert  
 
nstrftime: omit never-used code
diff --git a/build-aux/useless-if-before-free b/build-aux/useless-if-before-free
index ac9c890170..968e53062c 100755
--- a/build-aux/useless-if-before-free
+++ b/build-aux/useless-if-before-free
@@ -36,7 +36,7 @@
 eval 'exec perl -wSx "$0" "$@"'
  if 0;
 
-my $VERSION = '2022-01-27 18:51'; # UTC
+my $VERSION = '2024-06-17 03:44'; # UTC
 # The definition above must lie within the first 8 lines in order
 # for the Emacs time-stamp write hook (at end) to update it.
 # If you change this file with Emacs, please let the write hook
@@ -106,7 +106,7 @@ EOF
 sub is_NULL ($)
 {
   my ($expr) = @_;
-  return ($expr eq 'NULL' || $expr eq '0');
+  return ($expr eq 'NULL' || $expr eq 'nullptr' || $expr eq '0');
 }
 
 {
@@ -211,7 +211,7 @@ free=xfree
 git grep -l -z "$free *(" \
   | xargs -0 useless-if-before-free -l --name="$free" \
   | xargs -0 perl -0x3b -pi -e \
-   
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
+   
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL|nullptr))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
 
 # Use the following to remove redundant uses of kfree inside braces.
 # Note that -0777 puts perl in slurp-whole-file mode;
@@ -220,7 +220,7 @@ free=kfree
 git grep -l -z "$free *(" \
   | xargs -0 useless-if-before-free -l --name="$free" \
   | xargs -0 perl -0777 -pi -e \
- 
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
+ 
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL|nullptr))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
 
 Be careful that the result of the above transformation is valid.
 If the matched string is followed by "else", then obviously, it won't be.
-- 
2.45.2




Re: [PATCH] useless-if-before-free: Check for nullptr.

2024-06-16 Thread Collin Funk
Collin Funk wrote:
> -my $VERSION = '2022-01-27 18:51'; # UTC
> +my $VERSION = '2024-06-17 03:44'; # UTC

What is the point of time stamping the file? Reminds me of the old
SCCSID and RCSID stuff (which I have never used).

I mention it because in my emacs init file:

(setq enable-local-variables :safe)

Which avoids annoying prompts when entering directories with
'.dir-locals.el' files. However, I think the use of ':safe' prevents
the use of (eval ...) so I had to update it for the timestamp.

## eval: (add-hook 'before-save-hook 'time-stamp)

It looks like there is a way to deal with using 'safe-local-eval-forms'
but I wonder if these are really needed.

Collin