Two patches:
  - 0001 adds a unit test for the ALTMON_* items, that I forgot to add
    on 2018-01-24.
  - 0002 adds the ABALTMON_* items, specified by POSIX:2024.
    <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/langinfo.h.html>


2025-02-21  Bruno Haible  <br...@clisp.org>

        langinfo-h, nl_langinfo: Support abbreviated alternative month names.
        * lib/langinfo.in.h (ABALTMON_1...ABALTMON_12): New macros.
        * m4/langinfo_h.m4 (gl_LANGINFO_H): Define HAVE_LANGINFO_ABALTMON.
        * modules/langinfo-h (Makefile.am): Substitute HAVE_LANGINFO_ABALTMON.
        * tests/test-langinfo-h.c (items): Add ABALTMON_1 to ABALTMON_12.
        * lib/nl_langinfo.c (rpl_nl_langinfo): Treat ABALTMON_i like ABMON_i.
        * tests/test-nl_langinfo.c (main): Test ABALTMON_*.
        * doc/posix-headers/langinfo.texi: Document support of ABALTMON_*.
        * doc/posix-functions/nl_langinfo.texi: Likewise.

2025-02-21  Bruno Haible  <br...@clisp.org>

        langinfo-h tests: Verify that ALTMON_* are defined.
        * tests/test-langinfo-h.c (items): Add ALTMON_1 to ALTMON_12.

>From 02e566e8b3fe5b697555bd87ab4500a100507310 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 21 Feb 2025 18:42:22 +0100
Subject: [PATCH 1/2] langinfo-h tests: Verify that ALTMON_* are defined.

* tests/test-langinfo-h.c (items): Add ALTMON_1 to ALTMON_12.
---
 ChangeLog               |  5 +++++
 tests/test-langinfo-h.c | 12 ++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 4dc37bb1ef..8613924c4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2025-02-21  Bruno Haible  <br...@clisp.org>
+
+	langinfo-h tests: Verify that ALTMON_* are defined.
+	* tests/test-langinfo-h.c (items): Add ALTMON_1 to ALTMON_12.
+
 2025-02-21  Bruno Haible  <br...@clisp.org>
 
 	host-cpu-c-abi: Improve support for loongarch32.
diff --git a/tests/test-langinfo-h.c b/tests/test-langinfo-h.c
index c6d10c0a9a..869e37586b 100644
--- a/tests/test-langinfo-h.c
+++ b/tests/test-langinfo-h.c
@@ -61,6 +61,18 @@ int items[] =
     MON_10,
     MON_11,
     MON_12,
+    ALTMON_1,
+    ALTMON_2,
+    ALTMON_3,
+    ALTMON_4,
+    ALTMON_5,
+    ALTMON_6,
+    ALTMON_7,
+    ALTMON_8,
+    ALTMON_9,
+    ALTMON_10,
+    ALTMON_11,
+    ALTMON_12,
     ABMON_1,
     ABMON_2,
     ABMON_3,
-- 
2.43.0

>From 6e6eb2162eea328d1b85e68358441d1004f24be6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 21 Feb 2025 19:26:23 +0100
Subject: [PATCH 2/2] langinfo-h, nl_langinfo: Support abbreviated alternative
 month names.

* lib/langinfo.in.h (ABALTMON_1...ABALTMON_12): New macros.
* m4/langinfo_h.m4 (gl_LANGINFO_H): Define HAVE_LANGINFO_ABALTMON.
* modules/langinfo-h (Makefile.am): Substitute HAVE_LANGINFO_ABALTMON.
* tests/test-langinfo-h.c (items): Add ABALTMON_1 to ABALTMON_12.
* lib/nl_langinfo.c (rpl_nl_langinfo): Treat ABALTMON_i like ABMON_i.
* tests/test-nl_langinfo.c (main): Test ABALTMON_*.
* doc/posix-headers/langinfo.texi: Document support of ABALTMON_*.
* doc/posix-functions/nl_langinfo.texi: Likewise.
---
 ChangeLog                            | 12 +++++
 doc/posix-functions/nl_langinfo.texi |  6 ++-
 doc/posix-headers/langinfo.texi      |  4 ++
 lib/langinfo.in.h                    | 43 ++++++++++++++++
 lib/nl_langinfo.c                    | 75 +++++++++++++++++++---------
 m4/langinfo_h.m4                     | 17 ++++++-
 modules/langinfo-h                   |  1 +
 tests/test-langinfo-h.c              | 12 +++++
 tests/test-nl_langinfo1.c            | 26 ++++++++++
 9 files changed, 170 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8613924c4b..9e389ec0b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2025-02-21  Bruno Haible  <br...@clisp.org>
+
+	langinfo-h, nl_langinfo: Support abbreviated alternative month names.
+	* lib/langinfo.in.h (ABALTMON_1...ABALTMON_12): New macros.
+	* m4/langinfo_h.m4 (gl_LANGINFO_H): Define HAVE_LANGINFO_ABALTMON.
+	* modules/langinfo-h (Makefile.am): Substitute HAVE_LANGINFO_ABALTMON.
+	* tests/test-langinfo-h.c (items): Add ABALTMON_1 to ABALTMON_12.
+	* lib/nl_langinfo.c (rpl_nl_langinfo): Treat ABALTMON_i like ABMON_i.
+	* tests/test-nl_langinfo.c (main): Test ABALTMON_*.
+	* doc/posix-headers/langinfo.texi: Document support of ABALTMON_*.
+	* doc/posix-functions/nl_langinfo.texi: Likewise.
+
 2025-02-21  Bruno Haible  <br...@clisp.org>
 
 	langinfo-h tests: Verify that ALTMON_* are defined.
diff --git a/doc/posix-functions/nl_langinfo.texi b/doc/posix-functions/nl_langinfo.texi
index 2e2a6dc0d9..08894b5042 100644
--- a/doc/posix-functions/nl_langinfo.texi
+++ b/doc/posix-functions/nl_langinfo.texi
@@ -16,10 +16,14 @@
 The constant @code{CODESET} is not supported on some platforms:
 OpenBSD 3.8.
 @item
-The constants @code{ALTMON_1} to @code{ALTMON_12} are not defined on some
+The constants @code{ALTMON_1} to @code{ALTMON_12} are not supported on some
 platforms:
 glibc 2.26, musl libc, macOS 14, NetBSD 8.0, OpenBSD 7.5, AIX 7.2, HP-UX 11.31, Solaris 11.4, Haiku, Cygwin 2.9.
 @item
+The constants @code{ABALTMON_1} to @code{ABALTMON_12} are not supported on many
+platforms:
+glibc 2.41, musl libc, macOS 14, NetBSD 10.0, OpenBSD 7.6, AIX 7.3, HP-UX 11.31, Solaris 11.4, Haiku, Cygwin 3.5.
+@item
 The constants @code{ERA}, @code{ERA_D_FMT}, @code{ERA_D_T_FMT},
 @code{ERA_T_FMT}, @code{ALT_DIGITS} are not supported on some platforms:
 OpenBSD 7.5.
diff --git a/doc/posix-headers/langinfo.texi b/doc/posix-headers/langinfo.texi
index a0f8fcf593..988f3ca082 100644
--- a/doc/posix-headers/langinfo.texi
+++ b/doc/posix-headers/langinfo.texi
@@ -19,6 +19,10 @@
 platforms:
 glibc 2.26, musl libc, macOS 11.1, NetBSD 8.0, OpenBSD 7.5, AIX 7.2, HP-UX 11.31, Solaris 11.4, Haiku, Cygwin 2.9.
 @item
+The constants @code{ABALTMON_1} to @code{ABALTMON_12} are not defined on many
+platforms:
+glibc 2.41, musl libc, macOS 14, NetBSD 10.0, OpenBSD 7.6, AIX 7.3, HP-UX 11.31, Solaris 11.4, Haiku, Cygwin 3.5.
+@item
 The constants @code{ERA}, @code{ERA_D_FMT}, @code{ERA_D_T_FMT},
 @code{ERA_T_FMT}, @code{ALT_DIGITS} are not defined on some platforms:
 OpenBSD 7.5.
diff --git a/lib/langinfo.in.h b/lib/langinfo.in.h
index a1c4fe9b58..e16c95b3dd 100644
--- a/lib/langinfo.in.h
+++ b/lib/langinfo.in.h
@@ -115,6 +115,18 @@ typedef int nl_item;
 # define ABMON_10    (ABMON_1 + 9)
 # define ABMON_11    (ABMON_1 + 10)
 # define ABMON_12    (ABMON_1 + 11)
+# define ABALTMON_1  10220
+# define ABALTMON_2  (ABALTMON_1 + 1)
+# define ABALTMON_3  (ABALTMON_1 + 2)
+# define ABALTMON_4  (ABALTMON_1 + 3)
+# define ABALTMON_5  (ABALTMON_1 + 4)
+# define ABALTMON_6  (ABALTMON_1 + 5)
+# define ABALTMON_7  (ABALTMON_1 + 6)
+# define ABALTMON_8  (ABALTMON_1 + 7)
+# define ABALTMON_9  (ABALTMON_1 + 8)
+# define ABALTMON_10 (ABALTMON_1 + 9)
+# define ABALTMON_11 (ABALTMON_1 + 10)
+# define ABALTMON_12 (ABALTMON_1 + 11)
 # define ERA         10047
 # define ERA_D_FMT   10048
 # define ERA_D_T_FMT 10049
@@ -171,6 +183,37 @@ typedef int nl_item;
 #  define GNULIB_defined_ALTMON 1
 # endif
 
+# if !@HAVE_LANGINFO_ABALTMON@
+#  if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 27
+#   define ABALTMON_1  _NL_ABALTMON_1
+#   define ABALTMON_2  _NL_ABALTMON_2
+#   define ABALTMON_3  _NL_ABALTMON_3
+#   define ABALTMON_4  _NL_ABALTMON_4
+#   define ABALTMON_5  _NL_ABALTMON_5
+#   define ABALTMON_6  _NL_ABALTMON_6
+#   define ABALTMON_7  _NL_ABALTMON_7
+#   define ABALTMON_8  _NL_ABALTMON_8
+#   define ABALTMON_9  _NL_ABALTMON_9
+#   define ABALTMON_10 _NL_ABALTMON_10
+#   define ABALTMON_11 _NL_ABALTMON_11
+#   define ABALTMON_12 _NL_ABALTMON_12
+#  else
+#   define ABALTMON_1  10220
+#   define ABALTMON_2  (ABALTMON_1 + 1)
+#   define ABALTMON_3  (ABALTMON_1 + 2)
+#   define ABALTMON_4  (ABALTMON_1 + 3)
+#   define ABALTMON_5  (ABALTMON_1 + 4)
+#   define ABALTMON_6  (ABALTMON_1 + 5)
+#   define ABALTMON_7  (ABALTMON_1 + 6)
+#   define ABALTMON_8  (ABALTMON_1 + 7)
+#   define ABALTMON_9  (ABALTMON_1 + 8)
+#   define ABALTMON_10 (ABALTMON_1 + 9)
+#   define ABALTMON_11 (ABALTMON_1 + 10)
+#   define ABALTMON_12 (ABALTMON_1 + 11)
+#   define GNULIB_defined_ABALTMON 1
+#  endif
+# endif
+
 # if !@HAVE_LANGINFO_ERA@
 #  define ERA         10047
 #  define ERA_D_FMT   10048
diff --git a/lib/nl_langinfo.c b/lib/nl_langinfo.c
index e618e1fea1..f2a177cbd8 100644
--- a/lib/nl_langinfo.c
+++ b/lib/nl_langinfo.c
@@ -510,30 +510,57 @@ nl_langinfo (nl_item item)
           return result[item - ALTMON_1];
         }
     }
-    case ABMON_1:
-    case ABMON_2:
-    case ABMON_3:
-    case ABMON_4:
-    case ABMON_5:
-    case ABMON_6:
-    case ABMON_7:
-    case ABMON_8:
-    case ABMON_9:
-    case ABMON_10:
-    case ABMON_11:
-    case ABMON_12:
-      {
-        static char result[12][30];
-        static char const abmonths[][sizeof "Jan"] = {
-          "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
-          "Aug", "Sep", "Oct", "Nov", "Dec"
-        };
-        tmm.tm_mon = item - ABMON_1;
-        if (!strftime (buf, sizeof result[0], "%b", &tmm))
-          return (char *) abmonths[item - ABMON_1];
-        strcpy (result[item - ABMON_1], buf);
-        return result[item - ABMON_1];
-      }
+    {
+      static char const abmonths[][sizeof "Jan"] = {
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+        "Aug", "Sep", "Oct", "Nov", "Dec"
+      };
+      case ABMON_1:
+      case ABMON_2:
+      case ABMON_3:
+      case ABMON_4:
+      case ABMON_5:
+      case ABMON_6:
+      case ABMON_7:
+      case ABMON_8:
+      case ABMON_9:
+      case ABMON_10:
+      case ABMON_11:
+      case ABMON_12:
+        {
+          static char result[12][30];
+          tmm.tm_mon = item - ABMON_1;
+          if (!strftime (buf, sizeof result[0], "%b", &tmm))
+            return (char *) abmonths[item - ABMON_1];
+          strcpy (result[item - ABMON_1], buf);
+          return result[item - ABMON_1];
+        }
+      case ABALTMON_1:
+      case ABALTMON_2:
+      case ABALTMON_3:
+      case ABALTMON_4:
+      case ABALTMON_5:
+      case ABALTMON_6:
+      case ABALTMON_7:
+      case ABALTMON_8:
+      case ABALTMON_9:
+      case ABALTMON_10:
+      case ABALTMON_11:
+      case ABALTMON_12:
+        {
+          static char result[12][50];
+          tmm.tm_mon = item - ABALTMON_1;
+          /* The platforms without nl_langinfo() don't support strftime with
+             %Ob.  We don't even need to try.  */
+          #if 0
+          if (!strftime (buf, sizeof result[0], "%Ob", &tmm))
+          #endif
+            if (!strftime (buf, sizeof result[0], "%b", &tmm))
+              return (char *) abmonths[item - ABALTMON_1];
+          strcpy (result[item - ABALTMON_1], buf);
+          return result[item - ABALTMON_1];
+        }
+    }
     case ERA:
       return (char *) "";
     case ALT_DIGITS:
diff --git a/m4/langinfo_h.m4 b/m4/langinfo_h.m4
index c2bf7838d4..69f936f00c 100644
--- a/m4/langinfo_h.m4
+++ b/m4/langinfo_h.m4
@@ -1,5 +1,5 @@
 # langinfo_h.m4
-# serial 12
+# serial 13
 dnl Copyright (C) 2009-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -20,6 +20,7 @@ AC_DEFUN_ONCE([gl_LANGINFO_H]
   HAVE_LANGINFO_CODESET=0
   HAVE_LANGINFO_T_FMT_AMPM=0
   HAVE_LANGINFO_ALTMON=0
+  HAVE_LANGINFO_ABALTMON=0
   HAVE_LANGINFO_ERA=0
   HAVE_LANGINFO_YESEXPR=0
   AC_CHECK_HEADERS_ONCE([langinfo.h])
@@ -30,6 +31,7 @@ AC_DEFUN_ONCE([gl_LANGINFO_H]
     dnl ERA etc. are missing on OpenBSD 6.7.
     dnl T_FMT_AMPM and YESEXPR, NOEXPR are missing on IRIX 5.3.
     dnl ALTMON_* are missing on glibc 2.26 and many other systems.
+    dnl ABALTMON_* are missing on glibc 2.41 and many other systems.
     AC_CACHE_CHECK([whether langinfo.h defines CODESET],
       [gl_cv_header_langinfo_codeset],
       [AC_COMPILE_IFELSE(
@@ -66,6 +68,18 @@ AC_DEFUN_ONCE([gl_LANGINFO_H]
     if test $gl_cv_header_langinfo_altmon = yes; then
       HAVE_LANGINFO_ALTMON=1
     fi
+    AC_CACHE_CHECK([whether langinfo.h defines ABALTMON_1],
+      [gl_cv_header_langinfo_abaltmon],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM([[#include <langinfo.h>
+int a = ABALTMON_1;
+]])],
+         [gl_cv_header_langinfo_abaltmon=yes],
+         [gl_cv_header_langinfo_abaltmon=no])
+      ])
+    if test $gl_cv_header_langinfo_abaltmon = yes; then
+      HAVE_LANGINFO_ABALTMON=1
+    fi
     AC_CACHE_CHECK([whether langinfo.h defines ERA],
       [gl_cv_header_langinfo_era],
       [AC_COMPILE_IFELSE(
@@ -97,6 +111,7 @@ AC_DEFUN_ONCE([gl_LANGINFO_H]
   AC_SUBST([HAVE_LANGINFO_CODESET])
   AC_SUBST([HAVE_LANGINFO_T_FMT_AMPM])
   AC_SUBST([HAVE_LANGINFO_ALTMON])
+  AC_SUBST([HAVE_LANGINFO_ABALTMON])
   AC_SUBST([HAVE_LANGINFO_ERA])
   AC_SUBST([HAVE_LANGINFO_YESEXPR])
 
diff --git a/modules/langinfo-h b/modules/langinfo-h
index 24d14883b8..5370015a50 100644
--- a/modules/langinfo-h
+++ b/modules/langinfo-h
@@ -35,6 +35,7 @@ langinfo.h: langinfo.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_U
 	      -e 's|@''HAVE_LANGINFO_CODESET''@|$(HAVE_LANGINFO_CODESET)|g' \
 	      -e 's|@''HAVE_LANGINFO_T_FMT_AMPM''@|$(HAVE_LANGINFO_T_FMT_AMPM)|g' \
 	      -e 's|@''HAVE_LANGINFO_ALTMON''@|$(HAVE_LANGINFO_ALTMON)|g' \
+	      -e 's|@''HAVE_LANGINFO_ABALTMON''@|$(HAVE_LANGINFO_ABALTMON)|g' \
 	      -e 's|@''HAVE_LANGINFO_ERA''@|$(HAVE_LANGINFO_ERA)|g' \
 	      -e 's|@''HAVE_LANGINFO_YESEXPR''@|$(HAVE_LANGINFO_YESEXPR)|g' \
 	      -e 's|@''HAVE_NL_LANGINFO''@|$(HAVE_NL_LANGINFO)|g' \
diff --git a/tests/test-langinfo-h.c b/tests/test-langinfo-h.c
index 869e37586b..ca92aa71f7 100644
--- a/tests/test-langinfo-h.c
+++ b/tests/test-langinfo-h.c
@@ -85,6 +85,18 @@ int items[] =
     ABMON_10,
     ABMON_11,
     ABMON_12,
+    ABALTMON_1,
+    ABALTMON_2,
+    ABALTMON_3,
+    ABALTMON_4,
+    ABALTMON_5,
+    ABALTMON_6,
+    ABALTMON_7,
+    ABALTMON_8,
+    ABALTMON_9,
+    ABALTMON_10,
+    ABALTMON_11,
+    ABALTMON_12,
     ERA,
     ERA_D_FMT,
     ERA_D_T_FMT,
diff --git a/tests/test-nl_langinfo1.c b/tests/test-nl_langinfo1.c
index dbd0d54166..e08918d3fc 100644
--- a/tests/test-nl_langinfo1.c
+++ b/tests/test-nl_langinfo1.c
@@ -130,6 +130,32 @@ main (int argc, char *argv[])
   ASSERT (strlen (nl_langinfo (ABMON_10)) > 0);
   ASSERT (strlen (nl_langinfo (ABMON_11)) > 0);
   ASSERT (strlen (nl_langinfo (ABMON_12)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_1)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_2)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_3)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_4)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_5)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_6)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_7)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_8)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_9)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_10)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_11)) > 0);
+  ASSERT (strlen (nl_langinfo (ABALTMON_12)) > 0);
+  /* In the tested locales, abbreviated alternate month names and abbreviated
+     month names ought to be the same.  */
+  ASSERT (strcmp (nl_langinfo (ABALTMON_1), nl_langinfo (ABMON_1)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_2), nl_langinfo (ABMON_2)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_3), nl_langinfo (ABMON_3)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_4), nl_langinfo (ABMON_4)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_5), nl_langinfo (ABMON_5)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_6), nl_langinfo (ABMON_6)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_7), nl_langinfo (ABMON_7)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_8), nl_langinfo (ABMON_8)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_9), nl_langinfo (ABMON_9)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_10), nl_langinfo (ABMON_10)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_11), nl_langinfo (ABMON_11)) == 0);
+  ASSERT (strcmp (nl_langinfo (ABALTMON_12), nl_langinfo (ABMON_12)) == 0);
   ASSERT (strlen (nl_langinfo (ERA)) >= 0);
   ASSERT (strlen (nl_langinfo (ERA_D_FMT)) >= 0);
   ASSERT (strlen (nl_langinfo (ERA_D_T_FMT)) >= 0);
-- 
2.43.0

Reply via email to