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. Use AS_CASE so that Emacs can navigate this code better. * tests/test-stdlib.c (main): Check that MB_CUR_MAX compiles and is nonzero. --- ChangeLog | 14 ++++++++++++++ doc/posix-headers/stdlib.texi | 3 +++ lib/stdlib.in.h | 7 ++++++- m4/stdlib_h.m4 | 36 ++++++++++++++++++++--------------- tests/test-stdlib.c | 3 +++ 5 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 90a80123a2..416a05dd1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2024-12-23 Paul Eggert <egg...@cs.ucla.edu> + 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. Use AS_CASE + so that Emacs can navigate this code better. + * 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 3bd2d8e622..0763a20e0b 100644 --- a/doc/posix-headers/stdlib.texi +++ b/doc/posix-headers/stdlib.texi @@ -17,6 +17,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 43430dfe68..14f45cc21e 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -746,15 +746,20 @@ _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 _GL_STDLIB_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. */ int gl_mb_cur_max = MB_CUR_MAX; return gl_mb_cur_max == 3 ? 4 : gl_mb_cur_max; +# 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 87b63ff54e..f1192e3d25 100644 --- a/m4/stdlib_h.m4 +++ b/m4/stdlib_h.m4 @@ -1,5 +1,5 @@ # stdlib_h.m4 -# serial 82 +# serial 83 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, @@ -41,17 +41,17 @@ AC_DEFUN_ONCE([gl_STDLIB_H], AC_REQUIRE([gt_LOCALE_EN_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 + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include <stdlib.h> + ]], + [[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 and Haiku. - solaris* | haiku*) gl_cv_macro_MB_CUR_MAX_good="guessing no" ;; - # Guess yes otherwise. - *) gl_cv_macro_MB_CUR_MAX_good="guessing yes" ;; - esac -changequote([,])dnl + # Guess no on Solaris and Haiku, yes otherwise. + AS_CASE([$host_os], + [solaris* | haiku*], + [gl_cv_macro_MB_CUR_MAX_good="guessing no"], + [gl_cv_macro_MB_CUR_MAX_good="guessing yes"]) if test "$LOCALE_EN_UTF8" != none; then AC_RUN_IFELSE( [AC_LANG_SOURCE([[ @@ -71,11 +71,17 @@ int main () [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 ;; - esac + AS_CASE([$gl_cv_macro_MB_CUR_MAX_good], + [*yes], + [], + ["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)"]) AC_CHECK_DECLS_ONCE([ecvt]) if test $ac_cv_have_decl_ecvt = no; then 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.45.2