Subject: Re: [bug-diffutils] bug#79382: patch needed after gnulib changed

From: Paul Eggert <[email-masked]>
Date: Fri, 5 Sep 2025 15:55:19 -0700

Thanks, I installed that and am marking this bug report as done.

I used the opportunity to sync GNU diff with current Gnulib, causing a 
few minor changes to Gnulib.

I also installed the attached patch, to work around more the places 
where Gnulib drags in some multithreading and/or locale code that GNU 
diff (which is single-threaded and not that picky about locales) doesn't 
need. Not sure if these suggest any Gnulib changes.

From e124541148d38cd8b7f962aceb72fb44e7cc0aab Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Fri, 5 Sep 2025 09:56:13 -0700
Subject: [PATCH] maint: reduce Gnulib module usage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Recentish changes to Gnulib have pulled in more dependencies
on multithreading, locking, and whatnot.  Revamp to remove
these unwanted dependencies.
* bootstrap.conf: Also avoid hard-locale, localcharset,
localename-unsafe, localename-unsafe-limited.
Stop avoiding localename.
(avoided_gnulib_tests): New var.  Avoid these tests too.
(gnulib-modules): Remove hard-locale, nstrftime.
Add nstrftime-limited.
* configure.ac (gl_cv_func_mbrtowc_C_locale_sans_EILSEQ)
(gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ):
New vars, so that we do not worry about multibyte C locales.
(gl_THREADLIB_DEFAULT_NO): New macro.
Not sure how much it helps, but it can’t hurt.
(SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME): New macro.
* src/cmp.c: Do not include hard-locale.h.
(hard_locale_LC_MESSAGES): Assume that LC_MESSAGES is hard
if and only if "(C)" gets translated.  This drags in fewer
dependencies than calling hard_locale.
* src/diff.c: Include strftime.h instead of hard-locale.h.
(hard_locale_LC_TIME): New function, that uses nstrftime
to infer whether the time locale is hard.
(main): Use it instead of hard_locale.

maint: default Gnulib to no multithreading

* configure.ac: Define gl_THREADLIB_DEFAULT_NO
so that Gnulib defaults to no multithreading.
---
 bootstrap.conf | 26 +++++++++++++++++++++++---
 configure.ac   | 14 ++++++++++++++
 src/cmp.c      |  4 ++--
 src/diff.c     | 19 +++++++++++++++++--
 4 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index 73cc160..427a5f7 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -16,12 +16,32 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 avoided_gnulib_modules='
-  --avoid=localename
+  --avoid=hard-locale
+  --avoid=localcharset
+  --avoid=localename-unsafe
+  --avoid=localename-unsafe-limited
   --avoid=lock-tests
   --avoid=mbuiter
   --avoid=mbuiterf
   --avoid=setlocale
 '
+# These tests depend on localcharset, which we avoid.
+avoided_gnulib_tests='
+  --avoid=c32width-tests
+  --avoid=quotearg-simple-tests
+  --avoid=regex-tests
+  --avoid=wcwidth-tests
+'
+# These test whether all bytes are valid in the C locale,
+# which we don't care about.
+avoided_gnulib_tests=$avoided_gnulib_tests'
+  --avoid=btoc32-tests
+  --avoid=btowc-tests
+  --avoid=mbrtoc32-tests
+  --avoid=mbrtowc-tests
+  --avoid=mbsrtoc32s-tests
+  --avoid=mbsrtowcs-tests
+'
 
 # gnulib modules used by this package.
 gnulib_modules='
@@ -66,7 +86,6 @@ gnu-make
 gnu-web-doc-update
 gnumakefile
 gnupload
-hard-locale
 ialloc
 idx
 intprops
@@ -81,7 +100,7 @@ mempcpy
 minmax
 mkstemp
 mktime
-nstrftime
+nstrftime-limited
 nullptr
 openat
 pclose
@@ -149,6 +168,7 @@ gnulib_tool_option_extras="--tests-base=gnulib-tests
  --symlink
  --makefile-name=gnulib.mk
  $avoided_gnulib_modules
+ $avoided_gnulib_tests
 "
 
 # Build prerequisites
diff --git a/configure.ac b/configure.ac
index 7640124..aec74ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,18 @@ AC_PROG_AWK
 AC_PROG_CC
 AM_MISSING_PROG([HELP2MAN], [help2man])
 AC_PROG_RANLIB
+
+# Do not worry about multibyte C locales.
+# This removes dependencies on hard-locale etc.
+gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="guessing yes"
+gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ="guessing yes"
+
+# Default Gnulib configuration to no multithreading,
+# since diffutils is single-threaded.
+# Although the builder can override this with the --enable-threads option
+# of 'configure', diffutils does not support that on all platforms.
+m4_define([gl_THREADLIB_DEFAULT_NO])
+
 gl_EARLY
 gl_USE_SYSTEM_EXTENSIONS
 gl_INIT
@@ -61,6 +73,8 @@ AC_DEFINE([GNULIB_MBRTOC32_REGULAR], [1],
 
 AC_DEFINE([REQUIRE_GNUISH_STRFTIME_AM_PM], [0],
   [Do not worry about GNU strftime behavior for AM and PM indicators.])
+AC_DEFINE([SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME], [false],
+  [Do not worry about GNU strftime behavior for non-Gregorian calendars.])
 
 AC_C_INLINE
 
diff --git a/src/cmp.c b/src/cmp.c
index 2482708..0c4c80c 100644
--- a/src/cmp.c
+++ b/src/cmp.c
@@ -28,7 +28,6 @@
 #include <exitfail.h>
 #include <file-type.h>
 #include <getopt.h>
-#include <hard-locale.h>
 #include <progname.h>
 #include <quote.h>
 #include <unlocked-io.h>
@@ -50,7 +49,8 @@ static bool
 hard_locale_LC_MESSAGES (void)
 {
 #if defined LC_MESSAGES && ENABLE_NLS
-  return hard_locale (LC_MESSAGES);
+  static char const copyright_string[] = "(C)";
+  return gettext (copyright_string) != copyright_string;
 #else
   return false;
 #endif
diff --git a/src/diff.c b/src/diff.c
index 241e17c..8fd2e1a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -35,7 +35,7 @@
 #include <filenamecat.h>
 #include <fnmatch.h>
 #include <getopt.h>
-#include <hard-locale.h>
+#include <strftime.h>
 #include <progname.h>
 #include <quote.h>
 #include <sh-quote.h>
@@ -293,6 +293,21 @@ exclude_options (void)
 {
   return EXCLUDE_WILDCARDS | (ignore_file_name_case ? FNM_CASEFOLD : 0);
 }
+
+/* Return true if in a hard LC_TIME locale.  */
+static bool
+hard_locale_LC_TIME (void)
+{
+  /* Use the heuristic that %c has its usual POSIX meaning.
+     This is good enough in practice.  */
+  static struct tm const tm
+    = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1,
+	.tm_hour = 23, .tm_min = 59, .tm_sec = 59 };
+  static char const expected[] = "Thu Jan  1 23:59:59 1970";
+  char buf[sizeof expected];
+  return (nstrftime (buf, sizeof buf, "%c", &tm, 0, 0) == sizeof buf - 1
+	  && memcmp (buf, expected, sizeof buf) == 0);
+}
 
 int
 main (int argc, char **argv)
@@ -747,7 +762,7 @@ main (int argc, char **argv)
         specify_style (OUTPUT_NORMAL);
     }
 
-  if (output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME))
+  if (output_style != OUTPUT_CONTEXT || hard_locale_LC_TIME ())
     {
 #if defined STAT_TIMESPEC || defined STAT_TIMESPEC_NS
       time_format = "%Y-%m-%d %H:%M:%S.%N %z";
-- 
2.48.1