Subject: [PATCH] Try to install C.UTF-8 locale before falling back to C.

From: Tomas Volf <[email-masked]>
Date: Wed, 29 May 2024 20:00:03 +0200

If user does not have LANG or LC_ALL set (as does often happen in
various sandboxes) glibc will just install C locale.  That is fine (and
permissible by POSIX), however in Guile's context it is of a mixed
usefulness due to the absence of UTF-8 support.

This commit changes the locale auto-installation logic to attempt
C.UTF-8 locale first (if user did not request another one).

User can still get C locale by either GUILE_INSTALL_LOCALE=0 or LANG=C.
This default should be more useful in this day and age, at least for
Guile users.

* libguile/guile.c (should_install_default_locale): New function.
(main)[should_install_locale ()]: Try to install C.UTF-8 before falling
back to C.
* doc/ref/guile-invoke.texi (Environment Variables): Document the
change.
---
 doc/ref/guile-invoke.texi |  6 ++++--
 libguile/guile.c          | 19 +++++++++++++++++--
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/doc/ref/guile-invoke.texi b/doc/ref/guile-invoke.texi
index 856bce7b8..e08d78200 100644
--- a/doc/ref/guile-invoke.texi
+++ b/doc/ref/guile-invoke.texi
@@ -344,8 +344,10 @@ variable.  By default, the history file is @file{$HOME/.guile_history}.
 This is a flag that can be used to tell Guile whether or not to install
 the current locale at startup, via a call to @code{(setlocale LC_ALL
 "")}@footnote{The @code{GUILE_INSTALL_LOCALE} environment variable was
-ignored in Guile versions prior to 2.0.9.}.  @xref{Locales}, for more
-information on locales.
+ignored in Guile versions prior to 2.0.9.}.  If no explicit locale is
+set by the user (via @code{LC_ALL} or @code{LANG} environment
+variables), @samp{C.UTF-8} is tried before falling back to @samp{C}.
+@xref{Locales}, for more information on locales.
 
 You may explicitly indicate that you do not want to install
 the locale by setting @env{GUILE_INSTALL_LOCALE} to @code{0}, or
diff --git a/libguile/guile.c b/libguile/guile.c
index 8283ef6fa..a4ad10400 100644
--- a/libguile/guile.c
+++ b/libguile/guile.c
@@ -80,6 +80,16 @@ should_install_locale (void)
   return get_integer_from_environment ("GUILE_INSTALL_LOCALE", 1);
 }
 
+static int
+should_install_default_locale (void)
+{
+  /* This logic is derived from a precedence order described in section
+     8.2 of The Open Group Base Specifications Issue 7, 2018 edition. */
+  const char *lang   = getenv ("LANG");
+  const char *lc_all = getenv ("LC_ALL");
+  return (!lc_all || *lc_all == 0) && (!lang || *lang == 0);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -88,8 +98,13 @@ main (int argc, char **argv)
      error messages, use the right locale.  See
      <https://lists.gnu.org/archive/html/guile-devel/2011-11/msg00041.html>
      for the rationale.  */
-  if (should_install_locale () && setlocale (LC_ALL, "") == NULL)
-    fprintf (stderr, "guile: warning: failed to install locale\n");
+  if (should_install_locale ()) {
+    if (should_install_default_locale ()
+        && setlocale(LC_ALL, "C.UTF-8") != NULL)
+      ;
+    else if (setlocale (LC_ALL, "") == NULL)
+      fprintf (stderr, "guile: warning: failed to install locale\n");
+  }
 
   scm_boot_guile (argc, argv, inner_main, 0);
   return 0; /* never reached */
-- 
2.41.0