]> git.eshelyaron.com Git - emacs.git/commitdiff
Update from Gnulib by running admin/merge-gnulib
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 29 Jun 2024 23:08:28 +0000 (00:08 +0100)
committerEshel Yaron <me@eshelyaron.com>
Mon, 1 Jul 2024 07:49:27 +0000 (09:49 +0200)
* m4/wchar_t.m4: Remove; no longer needed.

(cherry picked from commit 4a8c8021cc311626fbfa55e68c524195ce466738)

23 files changed:
build-aux/gitlog-to-changelog
build-aux/install-sh
lib/acl-internal.c
lib/gnulib.mk.in
lib/stddef.in.h
lib/stdio.in.h
lib/strftime.c
lib/time-internal.h
lib/time.in.h
lib/time_rz.c
lib/timespec-add.c
lib/timespec-sub.c
m4/canonicalize.m4
m4/gnulib-comp.m4
m4/largefile.m4
m4/nstrftime.m4
m4/readlinkat.m4
m4/stddef_h.m4
m4/stdio_h.m4
m4/time_h.m4
m4/time_rz.m4
m4/tm_gmtoff.m4
m4/wchar_t.m4 [deleted file]

index 16a9405a7cb50200ef5f830dbd61bf29d46178e5..49e7ef95cef4155fddae2c2847790ed5031c8c17 100755 (executable)
@@ -495,7 +495,7 @@ sub git_dir_option($)
 
   # Complain about any unused entry in the --amend=F specified file.
   my $fail = 0;
-  foreach my $sha (keys %$amend_code)
+  foreach my $sha (sort keys %$amend_code)
     {
       warn "$ME:$amend_file: unused entry: $sha\n";
       $fail = 1;
index 7c56c9c015103600a06f59ab1183eb3966a513ab..b1d7a6f67f61f9fb53b653d557bdef8fbc1e20e0 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2023-11-23.18; # UTC
+scriptversion=2024-06-19.01; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -170,7 +170,7 @@ while test $# -ne 0; do
 
     -T) is_target_a_directory=never;;
 
-    --version) echo "$0 $scriptversion"; exit $?;;
+    --version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
 
     --) shift
         break;;
@@ -345,7 +345,7 @@ do
        ' 0
 
        # Because "mkdir -p" follows existing symlinks and we likely work
-       # directly in world-writeable /tmp, make sure that the '$tmpdir'
+       # directly in world-writable /tmp, make sure that the '$tmpdir'
        # directory is successfully created first before we actually test
        # 'mkdir -p'.
        if (umask $mkdir_umask &&
@@ -353,7 +353,7 @@ do
            exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
        then
          if test -z "$dir_arg" || {
-              # Check for POSIX incompatibilities with -m.
+              # Check for POSIX incompatibility with -m.
               # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
               # other-writable bit of parent directory when it shouldn't.
               # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
index 9ebb6e544b0936bd41aef4779caddc152a38f83b..ae5398306af2fd306b262753b76e6f22560c5b31 100644 (file)
@@ -89,6 +89,14 @@ acl_access_nontrivial (acl_t acl)
              group:Administrators:rwx
              mask::r-x
              other::r-x
+           or
+             user::rwx
+             group::r-x
+             group:SYSTEM:rwx
+             group:Administrators:rwx
+             group:Users:rwx
+             mask::rwx
+             other::r-x
          */
         case ACL_GROUP:
           {
@@ -105,9 +113,12 @@ acl_access_nontrivial (acl_t acl)
                     /* Ignore the ace if the group_sid is one of
                        - S-1-5-18 (group "SYSTEM")
                        - S-1-5-32-544 (group "Administrators")
-                       Cf. <https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids>  */
+                       - S-1-5-32-545 (group "Users")
+                       Cf. <https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids>
+                       and look at the output of the 'mkgroup' command.  */
                     ignorable = (strcmp (group_sid, "S-1-5-18") == 0
-                                 || strcmp (group_sid, "S-1-5-32-544") == 0);
+                                 || strcmp (group_sid, "S-1-5-32-544") == 0
+                                 || strcmp (group_sid, "S-1-5-32-545") == 0);
                   }
               }
             if (!ignorable)
index 832b245edc2fd6d9956add0f76846a965adfd1ba..948269e744d5f8e015cd477833cf20b4ae4f2a03 100644 (file)
@@ -545,6 +545,7 @@ GL_GNULIB_NANOSLEEP = @GL_GNULIB_NANOSLEEP@
 GL_GNULIB_NONBLOCKING = @GL_GNULIB_NONBLOCKING@
 GL_GNULIB_OBSTACK_PRINTF = @GL_GNULIB_OBSTACK_PRINTF@
 GL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GNULIB_OBSTACK_PRINTF_POSIX@
+GL_GNULIB_OBSTACK_ZPRINTF = @GL_GNULIB_OBSTACK_ZPRINTF@
 GL_GNULIB_OPEN = @GL_GNULIB_OPEN@
 GL_GNULIB_OPENAT = @GL_GNULIB_OPENAT@
 GL_GNULIB_OPENDIR = @GL_GNULIB_OPENDIR@
@@ -645,6 +646,7 @@ GL_GNULIB_TIME_RZ = @GL_GNULIB_TIME_RZ@
 GL_GNULIB_TMPFILE = @GL_GNULIB_TMPFILE@
 GL_GNULIB_TRUNCATE = @GL_GNULIB_TRUNCATE@
 GL_GNULIB_TTYNAME_R = @GL_GNULIB_TTYNAME_R@
+GL_GNULIB_TZNAME = @GL_GNULIB_TZNAME@
 GL_GNULIB_TZSET = @GL_GNULIB_TZSET@
 GL_GNULIB_UNISTD_H_GETOPT = @GL_GNULIB_UNISTD_H_GETOPT@
 GL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GNULIB_UNISTD_H_NONBLOCKING@
@@ -656,6 +658,7 @@ GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@
 GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@
 GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@
 GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@
+GL_GNULIB_VAZSPRINTF = @GL_GNULIB_VAZSPRINTF@
 GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@
 GL_GNULIB_VFPRINTF = @GL_GNULIB_VFPRINTF@
 GL_GNULIB_VFPRINTF_POSIX = @GL_GNULIB_VFPRINTF_POSIX@
@@ -665,8 +668,12 @@ GL_GNULIB_VPRINTF_POSIX = @GL_GNULIB_VPRINTF_POSIX@
 GL_GNULIB_VSCANF = @GL_GNULIB_VSCANF@
 GL_GNULIB_VSNPRINTF = @GL_GNULIB_VSNPRINTF@
 GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@
+GL_GNULIB_VZSNPRINTF = @GL_GNULIB_VZSNPRINTF@
+GL_GNULIB_VZSPRINTF = @GL_GNULIB_VZSPRINTF@
 GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@
 GL_GNULIB_WRITE = @GL_GNULIB_WRITE@
+GL_GNULIB_ZSNPRINTF = @GL_GNULIB_ZSNPRINTF@
+GL_GNULIB_ZSPRINTF = @GL_GNULIB_ZSPRINTF@
 GL_GNULIB__EXIT = @GL_GNULIB__EXIT@
 GL_STDC_BIT_CEIL = @GL_STDC_BIT_CEIL@
 GL_STDC_BIT_FLOOR = @GL_STDC_BIT_FLOOR@
@@ -928,7 +935,6 @@ HAVE_UTIMENSAT = @HAVE_UTIMENSAT@
 HAVE_VASPRINTF = @HAVE_VASPRINTF@
 HAVE_VDPRINTF = @HAVE_VDPRINTF@
 HAVE_WCHAR_H = @HAVE_WCHAR_H@
-HAVE_WCHAR_T = @HAVE_WCHAR_T@
 HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
 HAVE_XSERVER = @HAVE_XSERVER@
 HAVE__EXIT = @HAVE__EXIT@
@@ -1412,6 +1418,7 @@ XSYNC_CFLAGS = @XSYNC_CFLAGS@
 XSYNC_LIBS = @XSYNC_LIBS@
 XWIDGETS_OBJ = @XWIDGETS_OBJ@
 X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@
+ZIP = @ZIP@
 ZIPALIGN = @ZIPALIGN@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
@@ -3200,7 +3207,6 @@ stddef.h: stddef.in.h $(top_builddir)/config.status
              -e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \
              -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \
              -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \
-             -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \
              $(srcdir)/stddef.in.h > $@-t
        $(AM_V_at)mv $@-t $@
 else
@@ -3305,6 +3311,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
              -e 's/@''GNULIB_GETLINE''@/$(GL_GNULIB_GETLINE)/g' \
              -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GL_GNULIB_OBSTACK_PRINTF)/g' \
              -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GL_GNULIB_OBSTACK_PRINTF_POSIX)/g' \
+             -e 's/@''GNULIB_OBSTACK_ZPRINTF''@/$(GL_GNULIB_OBSTACK_ZPRINTF)/g' \
              -e 's/@''GNULIB_PCLOSE''@/$(GL_GNULIB_PCLOSE)/g' \
              -e 's/@''GNULIB_PERROR''@/$(GL_GNULIB_PERROR)/g' \
              -e 's/@''GNULIB_POPEN''@/$(GL_GNULIB_POPEN)/g' \
@@ -3323,6 +3330,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
              -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GL_GNULIB_STDIO_H_SIGPIPE)/g' \
              -e 's/@''GNULIB_TMPFILE''@/$(GL_GNULIB_TMPFILE)/g' \
              -e 's/@''GNULIB_VASPRINTF''@/$(GL_GNULIB_VASPRINTF)/g' \
+             -e 's/@''GNULIB_VAZSPRINTF''@/$(GL_GNULIB_VAZSPRINTF)/g' \
              -e 's/@''GNULIB_VDPRINTF''@/$(GL_GNULIB_VDPRINTF)/g' \
              -e 's/@''GNULIB_VFPRINTF''@/$(GL_GNULIB_VFPRINTF)/g' \
              -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GL_GNULIB_VFPRINTF_POSIX)/g' \
@@ -3332,6 +3340,10 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
              -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GL_GNULIB_VPRINTF_POSIX)/g' \
              -e 's/@''GNULIB_VSNPRINTF''@/$(GL_GNULIB_VSNPRINTF)/g' \
              -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GL_GNULIB_VSPRINTF_POSIX)/g' \
+             -e 's/@''GNULIB_VZSNPRINTF''@/$(GL_GNULIB_VZSNPRINTF)/g' \
+             -e 's/@''GNULIB_VZSPRINTF''@/$(GL_GNULIB_VZSPRINTF)/g' \
+             -e 's/@''GNULIB_ZSNPRINTF''@/$(GL_GNULIB_ZSNPRINTF)/g' \
+             -e 's/@''GNULIB_ZSPRINTF''@/$(GL_GNULIB_ZSPRINTF)/g' \
              -e 's/@''GNULIB_MDA_FCLOSEALL''@/$(GL_GNULIB_MDA_FCLOSEALL)/g' \
              -e 's/@''GNULIB_MDA_FDOPEN''@/$(GL_GNULIB_MDA_FDOPEN)/g' \
              -e 's/@''GNULIB_MDA_FILENO''@/$(GL_GNULIB_MDA_FILENO)/g' \
@@ -4005,6 +4017,7 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's/@''GNULIB_TIMESPEC_GETRES''@/$(GL_GNULIB_TIMESPEC_GETRES)/g' \
              -e 's/@''GNULIB_TIME_R''@/$(GL_GNULIB_TIME_R)/g' \
              -e 's/@''GNULIB_TIME_RZ''@/$(GL_GNULIB_TIME_RZ)/g' \
+             -e 's/@''GNULIB_TZNAME''@/$(GL_GNULIB_TZNAME)/g' \
              -e 's/@''GNULIB_TZSET''@/$(GL_GNULIB_TZSET)/g' \
              -e 's/@''GNULIB_MDA_TZSET''@/$(GL_GNULIB_MDA_TZSET)/g' \
              -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
index 63bb500e2621faf2774a8b369a0aed055c7c8cf6..0abc44970433110928922134341d433d4b7d1e46 100644 (file)
@@ -149,11 +149,6 @@ typedef long max_align_t;
 # endif
 #endif
 
-/* Some platforms lack wchar_t.  */
-#if !@HAVE_WCHAR_T@
-# define wchar_t int
-#endif
-
 /* Some platforms lack max_align_t.  The check for _GCC_MAX_ALIGN_T is
    a hack in case the configure-time test was done with g++ even though
    we are currently compiling with gcc.
index 1c0c9661bfeb61312642b457716f8532453ba7b1..cf2d8c999bcada55766a35d28c511af19f6dc128 100644 (file)
@@ -1075,13 +1075,39 @@ _GL_CXXALIASWARN (getw);
 # endif
 #endif
 
+#if @GNULIB_OBSTACK_ZPRINTF@
+struct obstack;
+/* Grows an obstack with formatted output.  Returns the number of
+   bytes added to OBS.  No trailing nul byte is added, and the
+   object should be closed with obstack_finish before use.
+   Upon memory allocation error, calls obstack_alloc_failed_handler.
+   Upon other error, returns -1 with errno set.
+
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is through
+   obstack_alloc_failed_handler.  */
+_GL_FUNCDECL_SYS (obstack_zprintf, ptrdiff_t,
+                  (struct obstack *obs, const char *format, ...)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (obstack_zprintf, ptrdiff_t,
+                  (struct obstack *obs, const char *format, ...));
+_GL_FUNCDECL_SYS (obstack_vzprintf, ptrdiff_t,
+                  (struct obstack *obs, const char *format, va_list args)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (obstack_vzprintf, ptrdiff_t,
+                  (struct obstack *obs, const char *format, va_list args));
+#endif
+
 #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
 struct obstack;
-/* Grow an obstack with formatted output.  Return the number of
+/* Grows an obstack with formatted output.  Returns the number of
    bytes added to OBS.  No trailing nul byte is added, and the
-   object should be closed with obstack_finish before use.  Upon
-   memory allocation error, call obstack_alloc_failed_handler.  Upon
-   other error, return -1.  */
+   object should be closed with obstack_finish before use.
+   Upon memory allocation error, calls obstack_alloc_failed_handler.
+   Upon other error, returns -1.  */
 # if @REPLACE_OBSTACK_PRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define obstack_printf rpl_obstack_printf
@@ -1433,7 +1459,31 @@ _GL_CXXALIASWARN (scanf);
 # endif
 #endif
 
+#if @GNULIB_ZSNPRINTF@
+/* Prints formatted output to string STR.  Similar to sprintf, but the
+   additional parameter SIZE limits how much is written into STR.
+   STR may be NULL, in which case nothing will be written.
+   Returns the string length of the formatted string (which may be larger
+   than SIZE).  Upon failure, returns -1 with errno set.
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is ENOMEM.  */
+_GL_FUNCDECL_SYS (zsnprintf, ptrdiff_t,
+                  (char *restrict str, size_t size,
+                   const char *restrict format, ...)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4)
+                  _GL_ARG_NONNULL ((3)));
+_GL_CXXALIAS_SYS (zsnprintf, ptrdiff_t,
+                  (char *restrict str, size_t size,
+                   const char *restrict format, ...));
+#endif
+
 #if @GNULIB_SNPRINTF@
+/* Prints formatted output to string STR.  Similar to sprintf, but the
+   additional parameter SIZE limits how much is written into STR.
+   STR may be NULL, in which case nothing will be written.
+   Returns the string length of the formatted string (which may be larger
+   than SIZE).  Upon failure, returns a negative value.  */
 # if @REPLACE_SNPRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define snprintf rpl_snprintf
@@ -1470,6 +1520,23 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - "
 # endif
 #endif
 
+#if @GNULIB_ZSPRINTF@
+/* Prints formatted output to string STR.
+   Returns the string length of the formatted string.  Upon failure,
+   returns -1 with errno set.
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is ENOMEM.  */
+_GL_FUNCDECL_SYS (zsprintf, ptrdiff_t,
+                  (char *restrict str,
+                   const char *restrict format, ...)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (zsprintf, ptrdiff_t,
+                  (char *restrict str,
+                   const char *restrict format, ...));
+#endif
+
 /* Some people would argue that all sprintf uses should be warned about
    (for example, OpenBSD issues a link warning for it),
    since it can cause security holes due to buffer overruns.
@@ -1480,6 +1547,9 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - "
    GNULIB_POSIXCHECK is defined.  */
 
 #if @GNULIB_SPRINTF_POSIX@
+/* Prints formatted output to string STR.
+   Returns the string length of the formatted string.  Upon failure,
+   returns a negative value.  */
 # if @REPLACE_SPRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define sprintf rpl_sprintf
@@ -1559,6 +1629,29 @@ _GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - "
 # endif
 #endif
 
+#if @GNULIB_VAZSPRINTF@
+/* Prints formatted output to a string dynamically allocated with malloc().
+   If the memory allocation succeeds, it stores the address of the string in
+   *RESULT and returns the number of resulting bytes, excluding the trailing
+   NUL.  Upon memory allocation error, or some other error, it returns -1
+   with errno set.
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is ENOMEM.  */
+_GL_FUNCDECL_SYS (azsprintf, ptrdiff_t,
+                  (char **result, const char *format, ...)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (azsprintf, ptrdiff_t,
+                  (char **result, const char *format, ...));
+_GL_FUNCDECL_SYS (vazsprintf, ptrdiff_t,
+                  (char **result, const char *format, va_list args)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (vazsprintf, ptrdiff_t,
+                  (char **result, const char *format, va_list args));
+#endif
+
 #if @GNULIB_VASPRINTF@
 /* Write formatted output to a string dynamically allocated with malloc().
    If the memory allocation succeeds, store the address of the string in
@@ -1769,7 +1862,31 @@ _GL_CXXALIASWARN (vscanf);
 # endif
 #endif
 
+#if @GNULIB_VZSNPRINTF@
+/* Prints formatted output to string STR.  Similar to sprintf, but the
+   additional parameter SIZE limits how much is written into STR.
+   STR may be NULL, in which case nothing will be written.
+   Returns the string length of the formatted string (which may be larger
+   than SIZE).  Upon failure, returns -1 with errno set.
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is ENOMEM.  */
+_GL_FUNCDECL_SYS (vzsnprintf, ptrdiff_t,
+                  (char *restrict str, size_t size,
+                   const char *restrict format, va_list args)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0)
+                  _GL_ARG_NONNULL ((3)));
+_GL_CXXALIAS_SYS (vzsnprintf, ptrdiff_t,
+                  (char *restrict str, size_t size,
+                   const char *restrict format, va_list args));
+#endif
+
 #if @GNULIB_VSNPRINTF@
+/* Prints formatted output to string STR.  Similar to vsprintf, but the
+   additional parameter SIZE limits how much is written into STR.
+   STR may be NULL, in which case nothing will be written.
+   Returns the string length of the formatted string (which may be larger
+   than SIZE).  Upon failure, returns a negative value.  */
 # if @REPLACE_VSNPRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define vsnprintf rpl_vsnprintf
@@ -1806,7 +1923,27 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - "
 # endif
 #endif
 
+#if @GNULIB_VZSPRINTF@
+/* Prints formatted output to string STR.
+   Returns the string length of the formatted string.  Upon failure,
+   returns -1 with errno set.
+   Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+   Therefore, if the format string is valid and does not use %ls/%lc
+   directives nor widths, the only possible failure code is ENOMEM.  */
+_GL_FUNCDECL_SYS (vzsprintf, ptrdiff_t,
+                  (char *restrict str,
+                   const char *restrict format, va_list args)
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_SYS (vzsprintf, ptrdiff_t,
+                  (char *restrict str,
+                   const char *restrict format, va_list args));
+#endif
+
 #if @GNULIB_VSPRINTF_POSIX@
+/* Prints formatted output to string STR.
+   Returns the string length of the formatted string.  Upon failure,
+   returns a negative value.  */
 # if @REPLACE_VSPRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define vsprintf rpl_vsprintf
index 5f1e76833f731ee3eefe6ac087c30532b4f17334..9b1b27a1fc8673a92d20892aa8f0b1cda1302f26 100644 (file)
@@ -25,9 +25,8 @@
 #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 1
 # include "../locale/localeinfo.h"
 #else
 # include <libc-config.h>
 #include <errno.h>
 #include <time.h>
 
-#if HAVE_TZNAME && !HAVE_DECL_TZNAME
-extern char *tzname[];
-#endif
-
 /* Do multibyte processing if multibyte encodings are supported, unless
    multibyte sequences are safe in formats.  Multibyte sequences are
    safe if they cannot contain byte sequences that look like format
@@ -87,18 +82,16 @@ extern char *tzname[];
 #endif
 
 #include <limits.h>
+#include <locale.h>
 #include <stdckdint.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 
-#if USE_C_LOCALE && HAVE_STRFTIME_L
-# include <locale.h>
-#endif
-
 #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
-# include <locale.h>
 # include "localename.h"
+#elif defined _WIN32 && !defined __CYGWIN__
+# include <wchar.h>
 #endif
 
 #include "attribute.h"
@@ -377,6 +370,15 @@ memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
 #endif
 
 
+/* Note: We assume that HAVE_STRFTIME_LZ implies HAVE_STRFTIME_L.
+   Otherwise, we would have to write (HAVE_STRFTIME_L || HAVE_STRFTIME_LZ)
+   instead of HAVE_STRFTIME_L everywhere.  */
+
+/* Define to 1 if we can use the system's native functions that takes a
+   timezone_t argument.  As of 2024, this is only true on NetBSD.  */
+#define HAVE_NATIVE_TIME_Z \
+  (USE_C_LOCALE && HAVE_STRFTIME_L ? HAVE_STRFTIME_LZ : HAVE_STRFTIME_Z)
+
 #if USE_C_LOCALE && HAVE_STRFTIME_L
 
 /* Cache for the C locale object.
@@ -396,6 +398,27 @@ c_locale (void)
 
 #endif
 
+#if HAVE_NATIVE_TIME_Z
+
+/* On NetBSD a null tz has undefined behavior, so use a non-null tz.
+   Cache the UTC time zone object in a volatile variable for improved
+   thread safety.  This is good enough in practice, although in theory
+   stdatomic.h should be used.  */
+static volatile timezone_t utc_timezone_cache;
+
+/* Return the UTC time zone object, or (timezone_t) 0 with errno set
+   if it cannot be created.  */
+static timezone_t
+utc_timezone (void)
+{
+  timezone_t tz = utc_timezone_cache;
+  if (!tz)
+    utc_timezone_cache = tz = tzalloc ("UTC0");
+  return tz;
+}
+
+#endif
+
 
 #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
 
@@ -747,7 +770,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
@@ -772,7 +795,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
 
 
 
@@ -810,9 +833,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
@@ -837,6 +860,200 @@ static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
                                    bool, enum pad_style, int, bool *
                                    extra_args_spec LOCALE_PARAM);
 
+#if !defined _LIBC \
+    && (!(USE_C_LOCALE && !HAVE_STRFTIME_L) || !HAVE_STRUCT_TM_TM_ZONE)
+
+/* Make sure we're calling the actual underlying strftime.
+   In some cases, time.h contains something like
+   "#define strftime rpl_strftime".  */
+# ifdef strftime
+#  undef strftime
+# endif
+
+/* Assuming the time zone is TZ, store into UBUF, of size UBUFSIZE, a
+   ' ' followed by the result of calling strftime with the format
+   "%MF" where M is MODIFIER (or is omitted if !MODIFIER) and F is
+   FORMAT_CHAR, along with the time information specified by *TP.
+   Return the number of bytes stored if successful, zero otherwise.  */
+static size_t
+underlying_strftime (timezone_t tz, char *ubuf, size_t ubufsize,
+                     char modifier, char format_char, struct tm const *tp)
+{
+  /* The relevant information is available only via the
+     underlying strftime implementation, so use that.  */
+  char ufmt[5];
+  char *u = ufmt;
+
+  /* The space helps distinguish strftime failure from empty
+     output.  */
+  *u++ = ' ';
+  *u++ = '%';
+  *u = modifier;
+  u += !!modifier;
+  *u++ = format_char;
+  *u = '\0';
+
+# if HAVE_NATIVE_TIME_Z
+  if (!tz)
+    {
+      tz = utc_timezone ();
+      if (!tz)
+        return 0; /* errno is set here */
+    }
+# endif
+
+# if !HAVE_NATIVE_TIME_Z
+  if (tz && tz != local_tz)
+    {
+      tz = set_tz (tz);
+      if (!tz)
+        return 0;
+    }
+# endif
+
+  size_t len;
+# if USE_C_LOCALE && HAVE_STRFTIME_L
+  locale_t locale = c_locale ();
+  if (!locale)
+    return 0; /* errno is set here */
+#  if HAVE_STRFTIME_LZ
+  len = strftime_lz (tz, ubuf, ubufsize, ufmt, tp, locale);
+#  else
+  len = strftime_l (ubuf, ubufsize, ufmt, tp, locale);
+#  endif
+# else
+#  if HAVE_STRFTIME_Z
+  len = strftime_z (tz, ubuf, ubufsize, ufmt, tp);
+#  else
+  len = strftime (ubuf, ubufsize, ufmt, tp);
+#  endif
+# endif
+
+# if !HAVE_NATIVE_TIME_Z
+  if (tz && !revert_tz (tz))
+    return 0;
+# endif
+
+  if (len != 0)
+    {
+# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ < 31) \
+      || defined __NetBSD__ || defined __sun)
+      /* glibc < 2.31, NetBSD, Solaris */
+      if (format_char == 'c')
+        {
+          /* The output of the strftime %c directive consists of the
+             date, the time, and the time zone.  But the time zone is
+             wrong, since neither TZ nor ZONE was passed as argument.
+             Therefore, remove the the last space-delimited word.
+             In order not to accidentally remove a date or a year
+             (that contains no letter) or an AM/PM indicator (that has
+             length 2), remove that last word only if it contains a
+             letter and has length >= 3.  */
+          char *space;
+          for (space = ubuf + len - 1; *space != ' '; space--)
+            continue;
+          if (space > ubuf)
+            {
+              /* Found a space.  */
+              if (strlen (space + 1) >= 3)
+                {
+                  /* The last word has length >= 3.  */
+                  bool found_letter = false;
+                  const char *p;
+                  for (p = space + 1; *p != '\0'; p++)
+                    if ((*p >= 'A' && *p <= 'Z')
+                        || (*p >= 'a' && *p <= 'z'))
+                      {
+                        found_letter = true;
+                        break;
+                      }
+                  if (found_letter)
+                    {
+                      /* The last word contains a letter.  */
+                      *space = '\0';
+                      len = space - ubuf;
+                    }
+                }
+            }
+        }
+#  if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
+      /* The output of the strftime %p and %r directives contains
+         an AM/PM indicator even for locales where it is not
+         suitable, such as French.  Remove this indicator.  */
+      if (format_char == 'p')
+        {
+          bool found_ampm = (len > 1);
+          if (found_ampm && should_remove_ampm ())
+            {
+              ubuf[1] = '\0';
+              len = 1;
+            }
+        }
+      else if (format_char == 'r')
+        {
+          char last_char = ubuf[len - 1];
+          bool found_ampm = !(last_char >= '0' && last_char <= '9');
+          if (found_ampm && should_remove_ampm ())
+            {
+              char *space;
+              for (space = ubuf + len - 1; *space != ' '; space--)
+                continue;
+              if (space > ubuf)
+                {
+                  *space = '\0';
+                  len = space - ubuf;
+                }
+            }
+        }
+#  endif
+# endif
+    }
+  return len;
+}
+#endif
+
+/* Return a time zone abbreviation for TZ.  Use BUF, of size BUFSIZE,
+   to store it if needed.  If MODIFIER use the strftime format
+   "%mZ" to format it, where m is the MODIFIER; otherwise
+   use plain "%Z".  Format an abbreviation appropriate for
+   TP and EXTRA_ARGS_SPEC.  Return the empty string on failure.  */
+static char const *
+get_tm_zone (timezone_t tz, char *ubuf, int ubufsize, int modifier,
+             struct tm const *tp)
+{
+#if HAVE_STRUCT_TM_TM_ZONE
+  /* The POSIX test suite assumes that setting
+     the environment variable TZ to a new value before calling strftime()
+     will influence the result (the %Z format) even if the information in
+     *TP is computed with a totally different time zone.
+     This is bogus: though POSIX allows bad behavior like this,
+     POSIX does not require it.  Do the right thing instead.  */
+  return tp->tm_zone;
+#else
+  if (!tz)
+    return "UTC";
+
+# if !HAVE_NATIVE_TIME_Z
+  timezone_t old_tz = tz;
+  if (tz != local_tz)
+    {
+      old_tz = set_tz (tz);
+      if (!old_tz)
+        return "";
+    }
+# endif
+
+  int zsize = underlying_strftime (tz, ubuf, ubufsize, 0, 'Z', tp);
+
+# if !HAVE_NATIVE_TIME_Z
+  if (!revert_tz (old_tz))
+    return "";
+# endif
+
+  return zsize ? ubuf + 1 : "";
+#endif
+}
+
 /* Write information from TP into S according to the format
    string FORMAT, writing no more that MAXSIZE characters
    (including the terminating '\0') and returning number of
@@ -927,10 +1144,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
 # define ap_len 2
 #endif
-#if HAVE_TZNAME
-  char **tzname_vec = tzname;
-#endif
-  const char *zone;
   size_t i = 0;
   STREAM_OR_CHAR_T *p = s;
   const CHAR_T *f;
@@ -938,47 +1151,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
   const char *format_end = NULL;
 #endif
 
-  zone = NULL;
-#if HAVE_STRUCT_TM_TM_ZONE
-  /* The POSIX test suite assumes that setting
-     the environment variable TZ to a new value before calling strftime()
-     will influence the result (the %Z format) even if the information in
-     TP is computed with a totally different time zone.
-     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
-  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;
   else
@@ -1293,7 +1465,21 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
           subfmt = L_("%a %b %e %H:%M:%S %Y");
 #elif defined _WIN32 && !defined __CYGWIN__
           /* On native Windows, "%c" is "%d/%m/%Y %H:%M:%S" by default.  */
-          subfmt = L_("%a %b %e %H:%M:%S %Y");
+          bool is_c_locale;
+          /* This code is equivalent to is_c_locale = !hard_locale (LC_TIME). */
+# if defined _MSC_VER
+          const wchar_t *locale = _wsetlocale (LC_TIME, NULL);
+          is_c_locale =
+            (wcscmp (locale, L"C") == 0 || wcscmp (locale, L"POSIX") == 0);
+# else
+          const char *locale = setlocale (LC_TIME, NULL);
+          is_c_locale =
+            (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0);
+# endif
+          if (is_c_locale)
+            subfmt = L_("%a %b %e %H:%M:%S %Y");
+          else
+            subfmt = L_("%a %e %b %Y %H:%M:%S");
 #else
           goto underlying_strftime;
 #endif
@@ -1314,40 +1500,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
           }
           break;
 
-#if !((defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) || (USE_C_LOCALE && !HAVE_STRFTIME_L))
+#if !defined _LIBC && !(USE_C_LOCALE && !HAVE_STRFTIME_L)
         underlying_strftime:
           {
-            /* The relevant information is available only via the
-               underlying strftime implementation, so use that.  */
-            char ufmt[5];
-            char *u = ufmt;
             char ubuf[1024]; /* enough for any single format in practice */
             size_t len;
-            /* Make sure we're calling the actual underlying strftime.
-               In some cases, config.h contains something like
-               "#define strftime rpl_strftime".  */
-# ifdef strftime
-#  undef strftime
-            size_t strftime (char *, size_t, const char *, struct tm const *);
-# endif
-
-            /* The space helps distinguish strftime failure from empty
-               output.  */
-            *u++ = ' ';
-            *u++ = '%';
-            if (modifier != 0)
-              *u++ = modifier;
-            *u++ = format_char;
-            *u = '\0';
-
-# if USE_C_LOCALE /* implies HAVE_STRFTIME_L */
-            locale_t locale = c_locale ();
-            if (!locale)
-              return 0; /* errno is set here */
-            len = strftime_l (ubuf, sizeof ubuf, ufmt, tp, locale);
-# else
-            len = strftime (ubuf, sizeof ubuf, ufmt, tp);
-# endif
+            len = underlying_strftime (tz, ubuf, sizeof ubuf,
+                                       modifier, format_char, tp);
             if (len != 0)
               {
 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 31) || defined __NetBSD__ || defined __sun /* glibc < 2.31, NetBSD, Solaris */
@@ -1715,7 +1874,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
           subfmt = L_("%I:%M:%S %p");
           goto subformat;
-#elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || (defined _WIN32 && !defined __CYGWIN__)
+#elif ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ \
+       || (defined _WIN32 && !defined __CYGWIN__))
           /* macOS, FreeBSD, native Windows strftime() may produce empty output
              for "%r".  */
           subfmt = L_("%I:%M:%S %p");
@@ -1927,8 +2087,30 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
               to_lowcase = true;
             }
 
+         {
+            char const *zone;
+#ifdef _LIBC
+            zone = tp->tm_zone;
+            /* 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.  */
+                if (!*tzset_called)
+                  {
+                    tzset ();
+                    *tzset_called = true;
+                  }
+                zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
+              }
+            if (! zone)
+              zone = "";
+#else
+            char zonebuf[128]; /* Enough for any time zone abbreviation.  */
+            zone = get_tm_zone (tz, zonebuf, sizeof zonebuf, modifier, tp);
+#endif
+
 #ifdef COMPILE_WIDE
-          {
             /* The zone string is always given in multibyte form.  We have
                to convert it to wide character.  */
             size_t w = pad == NO_PAD || width < 0 ? 0 : width;
@@ -1956,10 +2138,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
                 p += incr;
               }
             i += incr;
-          }
 #else
-          cpy (strlen (zone), zone);
+            cpy (strlen (zone), zone);
 #endif
+          }
           break;
 
         case L_(':'):
@@ -1984,7 +2166,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)
@@ -1995,16 +2177,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, &ltm);
@@ -2014,7 +2186,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
               }
 #endif
 
-            negative_number = diff < 0 || (diff == 0 && *zone == '-');
+            negative_number = diff < 0;
+            if (diff == 0)
+              {
+                char zonebuf[128]; /* Enough for any time zone abbreviation.  */
+                negative_number = (*get_tm_zone (tz, zonebuf, sizeof zonebuf,
+                                                 0, tp)
+                                   == '-');
+              }
             hour_diff = diff / 60 / 60;
             min_diff = diff / 60 % 60;
             sec_diff = diff % 60;
index 816684a11726828f1b345bf0426fb3bd5dde6103..3d778ba50ec6df5220a350f9fc0a227c3d712424 100644 (file)
@@ -17,6 +17,9 @@
 
 /* Written by Paul Eggert.  */
 
+/* This file is for Gnulib internal use only.
+   Applications should not use it.  */
+
 /* A time zone rule.  */
 struct tm_zone
 {
@@ -24,12 +27,6 @@ struct tm_zone
      members are zero.  */
   struct tm_zone *next;
 
-#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE
-  /* Copies of recent strings taken from tzname[0] and tzname[1].
-     The copies are in ABBRS, so that they survive tzset.  Null if unknown.  */
-  char *tzname_copy[2];
-#endif
-
   /* If nonzero, the rule represents the TZ environment variable set
      to the first "abbreviation" (this may be the empty string).
      Otherwise, it represents an unset TZ.  */
@@ -41,9 +38,17 @@ struct tm_zone
      actually a TZ environment value) may be empty.  Otherwise all
      strings must be nonempty.
 
-     Abbreviations are stored here because otherwise the values of
-     tm_zone and/or tzname would be dead after changing TZ and calling
+     Abbreviations are stored here even on platforms with tm_zone, because
+     otherwise tm_zone values would be dead after changing TZ and calling
      tzset.  Abbreviations never move once allocated, and are live
      until tzfree is called.  */
   char abbrs[FLEXIBLE_ARRAY_MEMBER];
 };
+
+timezone_t set_tz (timezone_t);
+bool revert_tz (timezone_t);
+
+/* Magic cookie timezone_t value, for local time.  It differs from
+   NULL and from all other timezone_t values.  Only the address
+   matters; the pointer is never dereferenced.  */
+#define local_tz ((timezone_t) 1)
index df99c8abca9b932e8427e1c37e931e563cb885f0..b91018937adc236ebac74905dcd35a8b31199ce0 100644 (file)
@@ -122,6 +122,23 @@ struct __time_t_must_be_integral {
 #  endif
 # endif
 
+# if @GNULIB_TZNAME@
+/* tzname[0..1]: Abbreviated time zone names, set by the tzset() function.  */
+#  if NEED_DECL_TZNAME
+extern
+#   ifdef __cplusplus
+  "C"
+#   endif
+  char *tzname[];
+#  endif
+#  if defined _WIN32 && !defined __CYGWIN__
+/* On native Windows, map 'tzname' to '_tzname' etc., so that -loldnames is not
+   required.  */
+#   undef tzname
+#   define tzname _tzname
+#  endif
+# endif
+
 /* Set *TS to the current time, and return BASE.
    Upon failure, return 0.  */
 # if @GNULIB_TIMESPEC_GET@
index 468d7539ce17a694f333090998bc3c602dcad9ab..a6523e1285b8e82c1b8dbfba795d5c7bcc85c5e4 100644 (file)
@@ -44,11 +44,6 @@ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
    used.  */
 enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) };
 
-/* Magic cookie timezone_t value, for local time.  It differs from
-   NULL and from all other timezone_t values.  Only the address
-   matters; the pointer is never dereferenced.  */
-static timezone_t const local_tz = (timezone_t) 1;
-
 /* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this
    includes its trailing null byte).  Append an extra null byte to
    mark the end of ABBRS.  */
@@ -70,9 +65,6 @@ tzalloc (char const *name)
   if (tz)
     {
       tz->next = NULL;
-#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE
-      tz->tzname_copy[0] = tz->tzname_copy[1] = NULL;
-#endif
       tz->tz_is_set = !!name;
       tz->abbrs[0] = '\0';
       if (name)
@@ -81,33 +73,16 @@ tzalloc (char const *name)
   return tz;
 }
 
-/* Save into TZ any nontrivial time zone abbreviation used by TM, and
-   update *TM (if HAVE_STRUCT_TM_TM_ZONE) or *TZ (if
-   !HAVE_STRUCT_TM_TM_ZONE && HAVE_TZNAME) if they use the abbreviation.
+/* If HAVE_STRUCT_TM_TM_ZONE, save into TZ any nontrivial time zone
+   abbreviation used by TM, and update *TM to contain the saved abbreviation.
    Return true if successful, false (setting errno) otherwise.  */
 static bool
 save_abbr (timezone_t tz, struct tm *tm)
 {
-#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME
-  char const *zone = NULL;
+#if HAVE_STRUCT_TM_TM_ZONE
+  char const *zone = tm->tm_zone;
   char *zone_copy = (char *) "";
 
-# if HAVE_TZNAME
-  int tzname_index = -1;
-# endif
-
-# if HAVE_STRUCT_TM_TM_ZONE
-  zone = tm->tm_zone;
-# endif
-
-# if HAVE_TZNAME
-  if (! (zone && *zone) && 0 <= tm->tm_isdst)
-    {
-      tzname_index = tm->tm_isdst != 0;
-      zone = tzname[tzname_index];
-    }
-# endif
-
   /* No need to replace null zones, or zones within the struct tm.  */
   if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1)))
     return true;
@@ -144,12 +119,7 @@ save_abbr (timezone_t tz, struct tm *tm)
     }
 
   /* Replace the zone name so that its lifetime matches that of TZ.  */
-# if HAVE_STRUCT_TM_TM_ZONE
   tm->tm_zone = zone_copy;
-# else
-  if (0 <= tzname_index)
-    tz->tzname_copy[tzname_index] = zone_copy;
-# endif
 #endif
 
   return true;
@@ -202,7 +172,7 @@ change_env (timezone_t tz)
    Return LOCAL_TZ if the time zone setting is already correct.
    Otherwise return a newly allocated time zone representing the old
    setting, or NULL (setting errno) on failure.  */
-static timezone_t
+timezone_t
 set_tz (timezone_t tz)
 {
   char *env_tz = getenv_TZ ();
@@ -229,7 +199,7 @@ set_tz (timezone_t tz)
 /* Restore an old setting returned by set_tz.  It must not be null.
    Return true (preserving errno) if successful, false (setting errno)
    otherwise.  */
-static bool
+bool
 revert_tz (timezone_t tz)
 {
   if (tz == local_tz)
@@ -302,9 +272,7 @@ mktime_z (timezone_t tz, struct tm *tm)
           tm_1.tm_isdst = tm->tm_isdst;
           time_t t = mktime (&tm_1);
           bool ok = 0 <= tm_1.tm_yday;
-#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME
           ok = ok && save_abbr (tz, &tm_1);
-#endif
           if (revert_tz (old_tz) && ok)
             {
               *tm = tm_1;
index e10c19842cd0d2a2861836c3e70a0cb645ee58b2..50683187117a185b7931e2788ca0ee38e53c1e4a 100644 (file)
 struct timespec
 timespec_add (struct timespec a, struct timespec b)
 {
-  time_t rs = a.tv_sec;
-  time_t bs = b.tv_sec;
-  int ns = a.tv_nsec + b.tv_nsec;
-  int nsd = ns - TIMESPEC_HZ;
-  int rns = ns;
-
-  if (0 <= nsd)
-    {
-      rns = nsd;
-      time_t bs1;
-      if (!ckd_add (&bs1, bs, 1))
-        bs = bs1;
-      else if (rs < 0)
-        rs++;
-      else
-        goto high_overflow;
-    }
-
-  if (ckd_add (&rs, rs, bs))
+  int nssum = a.tv_nsec + b.tv_nsec;
+  int carry = TIMESPEC_HZ <= nssum;
+  time_t rs;
+  int rns;
+  bool v = ckd_add (&rs, a.tv_sec, b.tv_sec);
+  if (v == ckd_add (&rs, rs, carry))
+    rns = nssum - TIMESPEC_HZ * carry;
+  else
     {
-      if (bs < 0)
+      if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs)
         {
           rs = TYPE_MINIMUM (time_t);
           rns = 0;
         }
       else
         {
-        high_overflow:
           rs = TYPE_MAXIMUM (time_t);
           rns = TIMESPEC_HZ - 1;
         }
index 315cc638369825264ce1caa876417a4c23551e5a..f6d948780e4dfa9cc3a6a8c0c83a13f21ff1dad5 100644 (file)
 struct timespec
 timespec_sub (struct timespec a, struct timespec b)
 {
-  time_t rs = a.tv_sec;
-  time_t bs = b.tv_sec;
-  int ns = a.tv_nsec - b.tv_nsec;
-  int rns = ns;
-
-  if (ns < 0)
-    {
-      rns = ns + TIMESPEC_HZ;
-      time_t bs1;
-      if (!ckd_add (&bs1, bs, 1))
-        bs = bs1;
-      else if (- TYPE_SIGNED (time_t) < rs)
-        rs--;
-      else
-        goto low_overflow;
-    }
-
-  if (ckd_sub (&rs, rs, bs))
+  int nsdiff = a.tv_nsec - b.tv_nsec;
+  bool borrow = nsdiff < 0;
+  time_t rs;
+  int rns;
+  bool v = ckd_sub (&rs, a.tv_sec, b.tv_sec);
+  if (v == ckd_sub (&rs, rs, borrow))
+    rns = nsdiff + TIMESPEC_HZ * borrow;
+  else
     {
-      if (0 < bs)
+      if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs)
         {
-        low_overflow:
           rs = TYPE_MINIMUM (time_t);
           rns = 0;
         }
index b63391a6ad7d4a397b306aaf3f427628c5c5d3f3..ec7aac470893d35f56b83fc3c9648da5cec5a38b 100644 (file)
@@ -1,5 +1,5 @@
 # canonicalize.m4
-# serial 39
+# serial 40
 
 dnl Copyright (C) 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
@@ -113,7 +113,7 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS],
             result |= 2;
           free (name);
         }
-        /* This test fails on Cygwin 2.9.  */
+        /* This test fails on macOS 14, Cygwin 2.9.  */
         #if HAVE_LSTAT
         {
           char *name = realpath ("conftest.l/../conftest.a", NULL);
@@ -122,7 +122,7 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS],
           free (name);
         }
         #endif
-        /* This test fails on Mac OS X 10.13, OpenBSD 6.0.  */
+        /* This test fails on macOS 14, OpenBSD 6.0.  */
         {
           char *name = realpath ("conftest.a/", NULL);
           if (name != NULL)
@@ -163,6 +163,8 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS],
         *-gnu* | gnu*)     gl_cv_func_realpath_works="guessing yes" ;;
                            # Guess 'nearly' on musl systems.
         *-musl*)           gl_cv_func_realpath_works="guessing nearly" ;;
+                           # Guess no on macOS.
+        darwin*)           gl_cv_func_realpath_works="guessing no" ;;
                            # Guess no on Cygwin.
         cygwin*)           gl_cv_func_realpath_works="guessing no" ;;
                            # Guess no on native Windows.
index 9af4b3a9fc870faf757e60e1a731c4b9ab784e2f..6c49edac93259c4f523508572666ef411c80a1c5 100644 (file)
@@ -1646,7 +1646,6 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/vararrays.m4
   m4/warn-on-use.m4
   m4/warnings.m4
-  m4/wchar_t.m4
   m4/wint_t.m4
   m4/xattr.m4
   m4/zzgnulib.m4
index 2f824089b0a93580f0f51764c152d5be2a7ba5e8..28813483594d1cacd22361037afab7c13e6e027e 100644 (file)
@@ -1,5 +1,5 @@
 # largefile.m4
-# serial 1
+# serial 2
 dnl Copyright 1992-1996, 1998-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,
@@ -88,7 +88,7 @@ m4_define([_AC_SYS_YEAR2038_OPTIONS], m4_normalize(
 # If you change this macro you may also need to change
 # _AC_SYS_YEAR2038_OPTIONS.
 AC_DEFUN([_AC_SYS_YEAR2038_PROBE],
-[AC_CACHE_CHECK([for $CPPFLAGS option for timestamps after 2038],
+[AC_CACHE_CHECK([for $CC option to support timestamps after 2038],
   [ac_cv_sys_year2038_opts],
   [ac_save_CPPFLAGS="$CPPFLAGS"
   ac_opt_found=no
@@ -234,7 +234,7 @@ m4_define([_AC_SYS_LARGEFILE_OPTIONS], m4_normalize(
 # If you change this macro you may also need to change
 # _AC_SYS_LARGEFILE_OPTIONS.
 AC_DEFUN([_AC_SYS_LARGEFILE_PROBE],
-[AC_CACHE_CHECK([for $CPPFLAGS option for large files],
+[AC_CACHE_CHECK([for $CC option to support large files],
   [ac_cv_sys_largefile_opts],
   [ac_save_CPPFLAGS=$CPPFLAGS
   ac_opt_found=no
index f73bca40ec103821c5c5fa1e7adfff0a71363dbc..534507d300baf54a5829fe305dd63539e4e0ba6e 100644 (file)
@@ -1,5 +1,5 @@
 # nstrftime.m4
-# serial 38
+# serial 40
 dnl Copyright (C) 1996-1997, 1999-2007, 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,
@@ -11,8 +11,6 @@ AC_DEFUN([gl_FUNC_GNU_STRFTIME],
 [
  AC_REQUIRE([AC_C_RESTRICT])
 
- # This defines (or not) HAVE_TZNAME and HAVE_STRUCT_TM_TM_ZONE.
- AC_REQUIRE([AC_STRUCT_TIMEZONE])
-
  AC_REQUIRE([gl_TM_GMTOFF])
+ AC_CHECK_FUNCS_ONCE([strftime_z])
 ])
index 1f091e8b636a5ac4e8d1f6329aafa41d493f265e..4c4e3588e0aa1ee0cc38cf89bf7b7f8f33cf20f9 100644 (file)
@@ -1,5 +1,5 @@
 # readlinkat.m4
-# serial 9
+# serial 10
 dnl Copyright (C) 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,
@@ -34,7 +34,7 @@ AC_DEFUN([gl_FUNC_READLINKAT],
          [gl_cv_decl_readlinkat_works=no])
       ])
     # Assume readlinkat has the same bugs as readlink,
-    # as is the case on OS X 10.10 with trailing slashes.
+    # as is the case on macOS 14 with trailing slashes.
     case $gl_cv_decl_readlinkat_works,$gl_cv_func_readlink_trailing_slash,$gl_cv_func_readlink_truncate in
       *yes,*yes,*yes)
         ;;
index 998fe12fa83e9819954dfc46423f2b421ad3cedd..c7f75b37fa03d2b8d3c697f3514a0c14ef7efac5 100644 (file)
@@ -1,5 +1,5 @@
 # stddef_h.m4
-# serial 16
+# serial 17
 dnl Copyright (C) 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,
@@ -10,7 +10,6 @@ dnl A placeholder for <stddef.h>, for platforms that have issues.
 AC_DEFUN_ONCE([gl_STDDEF_H],
 [
   AC_REQUIRE([gl_STDDEF_H_DEFAULTS])
-  AC_REQUIRE([gt_TYPE_WCHAR_T])
 
   dnl Persuade OpenBSD <stddef.h> to declare max_align_t.
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
@@ -52,11 +51,6 @@ AC_DEFUN_ONCE([gl_STDDEF_H],
     GL_GENERATE_STDDEF_H=true
   fi
 
-  if test $gt_cv_c_wchar_t = no; then
-    HAVE_WCHAR_T=0
-    GL_GENERATE_STDDEF_H=true
-  fi
-
   AC_CACHE_CHECK([whether NULL can be used in arbitrary expressions],
     [gl_cv_decl_null_works],
     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stddef.h>
@@ -148,5 +142,4 @@ AC_DEFUN([gl_STDDEF_H_DEFAULTS],
   STDDEF_NOT_IDEMPOTENT=0;       AC_SUBST([STDDEF_NOT_IDEMPOTENT])
   REPLACE_NULL=0;                AC_SUBST([REPLACE_NULL])
   HAVE_MAX_ALIGN_T=1;            AC_SUBST([HAVE_MAX_ALIGN_T])
-  HAVE_WCHAR_T=1;                AC_SUBST([HAVE_WCHAR_T])
 ])
index 8eb5816ad7e916aa05ed3a58c8fb41ddeaa4e3dd..10e1fbb8aa9073baa116474acfa4bfed9de4af1b 100644 (file)
@@ -1,5 +1,5 @@
 # stdio_h.m4
-# serial 63
+# serial 69
 dnl Copyright (C) 2007-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,
@@ -159,6 +159,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETLINE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_PRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_PRINTF_POSIX])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_ZPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PCLOSE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PERROR])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_POPEN])
@@ -177,6 +178,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDIO_H_SIGPIPE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TMPFILE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASPRINTF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VAZSPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VFSCANF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSCANF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VDPRINTF])
@@ -186,6 +188,10 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VPRINTF_POSIX])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSNPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSPRINTF_POSIX])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VZSNPRINTF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VZSPRINTF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ZSNPRINTF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ZSPRINTF])
     dnl Support Microsoft deprecated alias function names by default.
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_FCLOSEALL], [1])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_FDOPEN], [1])
index d2f3c9701cbd4ca0a501bc39548bc478ca9065d8..4ca7305792c370f30afd4e20ae000378c5e52acc 100644 (file)
@@ -1,5 +1,5 @@
 # time_h.m4
-# serial 25
+# serial 26
 dnl Copyright (C) 2000-2001, 2003-2007, 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,
@@ -145,6 +145,7 @@ AC_DEFUN([gl_TIME_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMESPEC_GETRES])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_R])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_RZ])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZNAME])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZSET])
     dnl Support Microsoft deprecated alias function names by default.
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_TZSET], [1])
index 8f45f2b1d3dca4a78e3a8fd81c0b5e386f247f9e..9613597aca0557219e6a76b7b30aadc702af2cbf 100644 (file)
@@ -1,5 +1,5 @@
 # time_rz.m4
-# serial 1
+# serial 2
 dnl Copyright (C) 2015-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,
@@ -13,7 +13,6 @@ AC_DEFUN([gl_TIME_RZ],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_TIME_H_DEFAULTS])
-  AC_REQUIRE([AC_STRUCT_TIMEZONE])
 
   # On Mac OS X 10.6, localtime loops forever with some time_t values.
   # See Bug#27706, Bug#27736, and
index 0c7dcb2a09aacdd7671919268bf5d420fc318296..3d97edb7a7fb3b2149b655689b66538817da846b 100644 (file)
@@ -1,15 +1,29 @@
 # tm_gmtoff.m4
-# serial 3
+# 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_MEMBER([struct tm.tm_gmtoff],
-                 [AC_DEFINE([HAVE_TM_GMTOFF], [1],
-                            [Define if struct tm has the tm_gmtoff member.])],
-                 ,
-                 [#include <time.h>])
+  AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [],
+    [[#include <time.h>
+    ]])
+
+  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_TM_GMTOFF.])])
 ])
diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4
deleted file mode 100644 (file)
index 968832c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# wchar_t.m4
-# serial 4 (gettext-0.18.2)
-dnl Copyright (C) 2002-2003, 2008-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 From Bruno Haible.
-dnl Test whether <stddef.h> has the 'wchar_t' type.
-dnl Prerequisite: AC_PROG_CC
-
-AC_DEFUN([gt_TYPE_WCHAR_T],
-[
-  AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t],
-    [AC_COMPILE_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include <stddef.h>
-            wchar_t foo = (wchar_t)'\0';]],
-          [[]])],
-       [gt_cv_c_wchar_t=yes],
-       [gt_cv_c_wchar_t=no])])
-  if test $gt_cv_c_wchar_t = yes; then
-    AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.])
-  fi
-])