From 2273c854ca1979c2073edd5d97cfccb933148eab Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 23 Dec 2024 12:57:12 -0800 Subject: [PATCH] stdlib: fix MB_CUR_MAX on older Android MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Android NDK r16 MB_CUR_MAX doesn’t link when compiling C. Problem found in GNU Emacs, which worked around it this way: https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=39a7e6b79fdeafc539a36f6831d922a2622cb679 ... but this ran afoul of the recent Gnulib change that added lib/stdlib.c. * lib/stdlib.in.h (gl_MB_CUR_MAX): If @REPLACE_MB_CUR_MAX@ is positive, use its value directly. * m4/stdlib_h.m4 (gl_STDLIB_H): Set REPLACE_MB_CUR_MAX to (-1) if the Solaris bug, and to 4 if the Android bug. * tests/test-stdlib.c (main): Check that MB_CUR_MAX compiles and is nonzero. --- ChangeLog | 13 ++++++++++ doc/posix-headers/stdlib.texi | 3 +++ lib/stdlib.in.h | 7 +++++- m4/stdlib_h.m4 | 47 +++++++++++++++++++++-------------- tests/test-stdlib.c | 3 +++ 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5cb8ad6482..8da0a60be9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2024-12-23 Paul Eggert + stdlib: fix MB_CUR_MAX on older Android + Android NDK r16 MB_CUR_MAX doesn’t link when compiling C. + Problem found in GNU Emacs, which worked around it this way: + https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=39a7e6b79fdeafc539a36f6831d922a2622cb679 + ... but this ran afoul of the recent Gnulib change that + added lib/stdlib.c. + * lib/stdlib.in.h (gl_MB_CUR_MAX): If @REPLACE_MB_CUR_MAX@ + is positive, use its value directly. + * m4/stdlib_h.m4 (gl_STDLIB_H): Set REPLACE_MB_CUR_MAX to (-1) + if the Solaris bug, and to 4 if the Android bug. + * tests/test-stdlib.c (main): Check that MB_CUR_MAX compiles + and is nonzero. + stdlib: MB_CUR_MAX is type size_t * lib/stdlib.in.h (gl_MB_CUR_MAX): Return size_t, not int, to conform to POSIX. diff --git a/doc/posix-headers/stdlib.texi b/doc/posix-headers/stdlib.texi index ac7efbda84..bd6b8ec4d8 100644 --- a/doc/posix-headers/stdlib.texi +++ b/doc/posix-headers/stdlib.texi @@ -15,6 +15,9 @@ Some platforms provide a @code{NULL} macro that cannot be used in arbitrary expressions: NetBSD 5.0 @item +Using the macro @code{MB_CUR_MAX} causes link errors on some platforms: +Android NDK r16. +@item The value of @code{MB_CUR_MAX} is too small (3 instead of 4) in UTF-8 locales on some platforms: Solaris 10. diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index 13dcc9cdf7..8233f6469b 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -729,14 +729,19 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " # endif #endif -/* Return maximum number of bytes of a multibyte character. */ +/* Return maximum number of bytes in a multibyte character in the + current locale. */ #if @REPLACE_MB_CUR_MAX@ # if !GNULIB_defined_MB_CUR_MAX static inline size_t gl_MB_CUR_MAX (void) { +# if 0 < @REPLACE_MB_CUR_MAX@ + return @REPLACE_MB_CUR_MAX@; +# else /* Turn the value 3 to the value 4, as needed for the UTF-8 encoding. */ return MB_CUR_MAX + (MB_CUR_MAX == 3); +# endif } # undef MB_CUR_MAX # define MB_CUR_MAX gl_MB_CUR_MAX () diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4 index bb5a646041..af1fbec785 100644 --- a/m4/stdlib_h.m4 +++ b/m4/stdlib_h.m4 @@ -1,5 +1,5 @@ # stdlib_h.m4 -# serial 78 +# serial 78.1 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, @@ -40,20 +40,24 @@ AC_DEFUN_ONCE([gl_STDLIB_H], AC_REQUIRE([gt_LOCALE_FR_UTF8]) AC_CACHE_CHECK([whether MB_CUR_MAX is correct], [gl_cv_macro_MB_CUR_MAX_good], - [ - dnl Initial guess, used when cross-compiling or when no suitable locale - dnl is present. + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include + ]], + [[return !!MB_CUR_MAX;]]) + ], + [dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. changequote(,)dnl - case "$host_os" in - # Guess no on Solaris. - solaris*) gl_cv_macro_MB_CUR_MAX_good="guessing no" ;; - # Guess yes otherwise. - *) gl_cv_macro_MB_CUR_MAX_good="guessing yes" ;; - esac + case "$host_os" in + # Guess no on Solaris. + solaris*) gl_cv_macro_MB_CUR_MAX_good="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_macro_MB_CUR_MAX_good="guessing yes" ;; + esac changequote([,])dnl - if test $LOCALE_FR_UTF8 != none; then - AC_RUN_IFELSE( - [AC_LANG_SOURCE([[ + if test $LOCALE_FR_UTF8 != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ #include #include int main () @@ -66,14 +70,21 @@ int main () } return result; }]])], - [gl_cv_macro_MB_CUR_MAX_good=yes], - [gl_cv_macro_MB_CUR_MAX_good=no], - [:]) - fi + [gl_cv_macro_MB_CUR_MAX_good=yes], + [gl_cv_macro_MB_CUR_MAX_good=no], + [:]) + fi + ], + [gl_cv_macro_MB_CUR_MAX_good="link failed - so no"]) ]) case "$gl_cv_macro_MB_CUR_MAX_good" in *yes) ;; - *) REPLACE_MB_CUR_MAX=1 ;; + "link failed - so no") + # 4 suffices as a workaround in Android NDK 16, + # the only known platform with the bug. + REPLACE_MB_CUR_MAX=4 + ;; + *) REPLACE_MB_CUR_MAX="(-1)" ;; esac AC_CHECK_DECLS_ONCE([ecvt]) diff --git a/tests/test-stdlib.c b/tests/test-stdlib.c index cb6db8028f..7b9cd50a79 100644 --- a/tests/test-stdlib.c +++ b/tests/test-stdlib.c @@ -56,6 +56,9 @@ main (void) return 1; #endif + if (MB_CUR_MAX == 0) + return 1; + if (test_sys_wait_macros ()) return 2; -- 2.39.5