summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2023-04-28 01:12:16 +0200
committerBruno Haible <bruno@clisp.org>2023-04-28 01:12:16 +0200
commitefb17ec15925db925088e801920a3df17b11ac49 (patch)
tree10c5fc1d895d3737c340d67b8db3d2b366727e7d
parentfedd186a0b85045d2a1446abbb17eb9151bf0e11 (diff)
downloadgnulib-efb17ec15925db925088e801920a3df17b11ac49.tar.gz
localeconv: Work around a mingw bug.
* m4/localeconv.m4 (gl_FUNC_LOCALECONV): Test whether fields of type 'char' are filled correctly. (gl_PREREQ_LOCALECONV): Test whether 'struct lconv' has the int_{p,n}_* members. * lib/localeconv.c (FIX_CHAR_VALUE): New macro. (localeconv): Replace negative field values with CHAR_MAX. * doc/posix-functions/localeconv.texi: Mention the mingw bug.
-rw-r--r--ChangeLog11
-rw-r--r--doc/posix-functions/localeconv.texi4
-rw-r--r--lib/localeconv.c45
-rw-r--r--m4/localeconv.m439
4 files changed, 81 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index a41aeff43e..3932a30ae1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2023-04-27 Bruno Haible <bruno@clisp.org>
+ localeconv: Work around a mingw bug.
+ * m4/localeconv.m4 (gl_FUNC_LOCALECONV): Test whether fields of type
+ 'char' are filled correctly.
+ (gl_PREREQ_LOCALECONV): Test whether 'struct lconv' has the int_{p,n}_*
+ members.
+ * lib/localeconv.c (FIX_CHAR_VALUE): New macro.
+ (localeconv): Replace negative field values with CHAR_MAX.
+ * doc/posix-functions/localeconv.texi: Mention the mingw bug.
+
+2023-04-27 Bruno Haible <bruno@clisp.org>
+
stdlib: Fix error when cross-compiling (regression 2023-04-04).
Reported by Pierre Labastie <pierre.labastie@neuf.fr> in
<https://lists.gnu.org/archive/html/bug-gnulib/2023-04/msg00220.html>.
diff --git a/doc/posix-functions/localeconv.texi b/doc/posix-functions/localeconv.texi
index 22a19ca3d3..ebcc5a5b29 100644
--- a/doc/posix-functions/localeconv.texi
+++ b/doc/posix-functions/localeconv.texi
@@ -17,6 +17,10 @@ The @code{struct lconv} type does not contain the members
@code{int_n_cs_precedes}, @code{int_n_sign_posn}, @code{int_n_sep_by_space}
on some platforms:
glibc, OpenBSD 4.9, HP-UX 11, IRIX 6.5, Solaris 11.4, Cygwin 1.5.x, mingw, MSVC 14.
+@item
+The values of fields of @code{struct lconv} of type @code{char} are -1 instead
+of CHAR_MAX on some platforms:
+mingw.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/localeconv.c b/lib/localeconv.c
index 60c050f486..c1a34baa05 100644
--- a/lib/localeconv.c
+++ b/lib/localeconv.c
@@ -19,10 +19,14 @@
/* Specification. */
#include <locale.h>
+#include <limits.h>
+
#if HAVE_STRUCT_LCONV_DECIMAL_POINT
+# define FIX_CHAR_VALUE(x) ((x) >= 0 ? (x) : CHAR_MAX)
+
/* Override for platforms where 'struct lconv' lacks the int_p_*, int_n_*
- members. */
+ members or where fields of type 'char' are set to -1 instead of CHAR_MAX. */
struct lconv *
localeconv (void)
@@ -41,21 +45,30 @@ localeconv (void)
result.positive_sign = sys_result->positive_sign;
result.negative_sign = sys_result->negative_sign;
result.currency_symbol = sys_result->currency_symbol;
- result.frac_digits = sys_result->frac_digits;
- result.p_cs_precedes = sys_result->p_cs_precedes;
- result.p_sign_posn = sys_result->p_sign_posn;
- result.p_sep_by_space = sys_result->p_sep_by_space;
- result.n_cs_precedes = sys_result->n_cs_precedes;
- result.n_sign_posn = sys_result->n_sign_posn;
- result.n_sep_by_space = sys_result->n_sep_by_space;
+ result.frac_digits = FIX_CHAR_VALUE (sys_result->frac_digits);
+ result.p_cs_precedes = FIX_CHAR_VALUE (sys_result->p_cs_precedes);
+ result.p_sign_posn = FIX_CHAR_VALUE (sys_result->p_sign_posn);
+ result.p_sep_by_space = FIX_CHAR_VALUE (sys_result->p_sep_by_space);
+ result.n_cs_precedes = FIX_CHAR_VALUE (sys_result->n_cs_precedes);
+ result.n_sign_posn = FIX_CHAR_VALUE (sys_result->n_sign_posn);
+ result.n_sep_by_space = FIX_CHAR_VALUE (sys_result->n_sep_by_space);
result.int_curr_symbol = sys_result->int_curr_symbol;
- result.int_frac_digits = sys_result->int_frac_digits;
- result.int_p_cs_precedes = sys_result->p_cs_precedes;
- result.int_p_sign_posn = sys_result->p_sign_posn;
- result.int_p_sep_by_space = sys_result->p_sep_by_space;
- result.int_n_cs_precedes = sys_result->n_cs_precedes;
- result.int_n_sign_posn = sys_result->n_sign_posn;
- result.int_n_sep_by_space = sys_result->n_sep_by_space;
+ result.int_frac_digits = FIX_CHAR_VALUE (sys_result->int_frac_digits);
+# if HAVE_STRUCT_LCONV_INT_P_CS_PRECEDES
+ result.int_p_cs_precedes = FIX_CHAR_VALUE (sys_result->int_p_cs_precedes);
+ result.int_p_sign_posn = FIX_CHAR_VALUE (sys_result->int_p_sign_posn);
+ result.int_p_sep_by_space = FIX_CHAR_VALUE (sys_result->int_p_sep_by_space);
+ result.int_n_cs_precedes = FIX_CHAR_VALUE (sys_result->int_n_cs_precedes);
+ result.int_n_sign_posn = FIX_CHAR_VALUE (sys_result->int_n_sign_posn);
+ result.int_n_sep_by_space = FIX_CHAR_VALUE (sys_result->int_n_sep_by_space);
+# else
+ result.int_p_cs_precedes = FIX_CHAR_VALUE (sys_result->p_cs_precedes);
+ result.int_p_sign_posn = FIX_CHAR_VALUE (sys_result->p_sign_posn);
+ result.int_p_sep_by_space = FIX_CHAR_VALUE (sys_result->p_sep_by_space);
+ result.int_n_cs_precedes = FIX_CHAR_VALUE (sys_result->n_cs_precedes);
+ result.int_n_sign_posn = FIX_CHAR_VALUE (sys_result->n_sign_posn);
+ result.int_n_sep_by_space = FIX_CHAR_VALUE (sys_result->n_sep_by_space);
+# endif
return &result;
}
@@ -64,8 +77,6 @@ localeconv (void)
/* Override for platforms where 'struct lconv' is a dummy. */
-# include <limits.h>
-
struct lconv *
localeconv (void)
{
diff --git a/m4/localeconv.m4 b/m4/localeconv.m4
index ae225fed66..374dcbf54f 100644
--- a/m4/localeconv.m4
+++ b/m4/localeconv.m4
@@ -1,4 +1,4 @@
-# localeconv.m4 serial 1
+# localeconv.m4 serial 2
dnl Copyright (C) 2012-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -8,10 +8,45 @@ AC_DEFUN([gl_FUNC_LOCALECONV],
[
AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
AC_REQUIRE([gl_LOCALE_H])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
if test $REPLACE_STRUCT_LCONV = 1; then
REPLACE_LOCALECONV=1
fi
+ if test $REPLACE_LOCALECONV = 0; then
+ dnl Test whether fields of type 'char' are filled correctly.
+ dnl This test fails on mingw 5.0.3.
+ AC_CACHE_CHECK([whether localeconv works],
+ [gl_cv_func_localeconv_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+ #include <locale.h>
+ #include <limits.h>
+ int main ()
+ {
+ struct lconv *l = localeconv ();
+ return l->frac_digits != CHAR_MAX && l->frac_digits < 0;
+ }
+ ]])],
+ [gl_cv_func_localeconv_works=yes],
+ [gl_cv_func_localeconv_works=no],
+ [case "$host_os" in
+ # Guess yes on glibc systems.
+ *-gnu* | gnu*) gl_cv_func_localeconv_works="guessing yes" ;;
+ # Guess yes on musl systems.
+ *-musl* | midipix*) gl_cv_func_localeconv_works="guessing yes" ;;
+ # Guess no on native Windows.
+ mingw*) gl_cv_func_localeconv_works="guessing no" ;;
+ # If we don't know, obey --enable-cross-guesses.
+ *) gl_cv_func_localeconv_works="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ ])
+ case "$gl_cv_func_localeconv_works" in
+ *yes) ;;
+ *) REPLACE_LOCALECONV=1 ;;
+ esac
+ fi
])
# Prerequisites of lib/localeconv.c.
@@ -19,4 +54,6 @@ AC_DEFUN([gl_PREREQ_LOCALECONV],
[
AC_CHECK_MEMBERS([struct lconv.decimal_point], [], [],
[[#include <locale.h>]])
+ AC_CHECK_MEMBERS([struct lconv.int_p_cs_precedes], [], [],
+ [[#include <locale.h>]])
])