From efb17ec15925db925088e801920a3df17b11ac49 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 28 Apr 2023 01:12:16 +0200 Subject: 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. --- ChangeLog | 11 +++++++++ doc/posix-functions/localeconv.texi | 4 ++++ lib/localeconv.c | 45 +++++++++++++++++++++++-------------- m4/localeconv.m4 | 39 +++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index a41aeff43e..3932a30ae1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2023-04-27 Bruno Haible + + 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 stdlib: Fix error when cross-compiling (regression 2023-04-04). 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 +#include + #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 - 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 + #include + 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 ]]) + AC_CHECK_MEMBERS([struct lconv.int_p_cs_precedes], [], [], + [[#include ]]) ]) -- cgit v1.2.1