bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: android bionc has dummy lconv


From: Bruno Haible
Subject: Re: android bionc has dummy lconv
Date: Sun, 25 Mar 2012 13:30:34 +0200
User-agent: KMail/4.7.4 (Linux/3.1.0-1.2-desktop; KDE/4.7.4; x86_64; ; )

Gianluigi Tiesi wrote:
> sorry (sent the first email by mistake)
> 
> #if 1 /* MISSING FROM BIONIC - DEFINED TO MAKE libstdc++-v3 happy */
> struct lconv { };
> struct lconv *localeconv(void);
> #endif /* MISSING */
> ...
> android bionic hasn't locale support by design)

Thanks for the info.

> the only problem is in gnulib nl_langinfo.c at 154
> 
>      case RADIXCHAR:
>        return localeconv () ->decimal_point;
>      case THOUSEP:
>        return localeconv () ->thousands_sep;
>      /* nl_langinfo items of the LC_TIME category.
>         TODO: Really use the locale.  */

There are more uses, also in human.c and vasnprintf.c.

> disable the module at all

The gnulib philosophy is that the developer can program according to POSIX
and Glibc APIs, even on deficient platforms.

Here's the first part of a supposed fix.


2012-03-25  Bruno Haible  <address@hidden>

        locale: Provide a working 'struct lconv'.
        * lib/locale.in.h (lconv): Override if REPLACE_STRUCT_LCONV is 1.
        * m4/locale_h.m4 (gl_LOCALE_H): Set REPLACE_STRUCT_LCONV to 1 if
        'struct lconv' does not even contain decimal_point.
        (gl_LOCALE_H_DEFAULTS): Initialize REPLACE_STRUCT_LCONV.
        * modules/locale (Makefile.am): Substitute REPLACE_STRUCT_LCONV.
        * tests/test-locale.c (main): Check that 'struct lconv' is complete.
        * doc/posix-headers/locale.texi: Mention the problems with
        'struct lconv'.
        Reported by Gianluigi Tiesi <address@hidden>.

--- doc/posix-headers/locale.texi.orig  Sun Mar 25 13:20:43 2012
+++ doc/posix-headers/locale.texi       Sun Mar 25 13:13:08 2012
@@ -16,6 +16,17 @@
 glibc 2.11, MacOS X 10.5.
 
 @item
+The @code{struct lconv} type does not contain any members on some platforms:
+Android.
+
address@hidden
+The @code{struct lconv} type does not contain the members
address@hidden, @code{int_p_sign_posn}, @code{int_p_sep_by_space},
address@hidden, @code{int_n_sign_posn}, @code{int_n_sep_by_space}
+on some platforms:
+glibc.
+
address@hidden
 Some platforms provide a @code{NULL} macro that cannot be used in arbitrary
 expressions:
 NetBSD 5.0
@@ -23,4 +34,10 @@
 
 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
+The @code{struct lconv} type does not contain the members
address@hidden, @code{int_p_sign_posn}, @code{int_p_sep_by_space},
address@hidden, @code{int_n_sign_posn}, @code{int_n_sep_by_space}
+on some platforms:
+OpenBSD 4.9, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 11 2011-11, Cygwin 1.5.x, 
mingw, MSVC 9.
 @end itemize
--- lib/locale.in.h.orig        Sun Mar 25 13:20:43 2012
+++ lib/locale.in.h     Sun Mar 25 13:15:06 2012
@@ -47,6 +47,87 @@
 # define LC_MESSAGES 1729
 #endif
 
+/* Bionic libc's 'struct lconv' is just a dummy.  */
+#if @REPLACE_STRUCT_LCONV@
+# define lconv rpl_lconv
+struct lconv
+{
+  /* All 'char *' are actually 'const char *'.  */
+
+  /* Members that depend on the LC_NUMERIC category of the locale.  See
+     
<http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04>
 */
+
+  /* Symbol used as decimal point.  */
+  char *decimal_point;
+  /* Symbol used to separate groups of digits to the left of the decimal
+     point.  */
+  char *thousands_sep;
+  /* Definition of the size of groups of digits to the left of the decimal
+     point.  */
+  char *grouping;
+
+  /* Members that depend on the LC_MONETARY category of the locale.  See
+     
<http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03>
 */
+
+  /* Symbol used as decimal point.  */
+  char *mon_decimal_point;
+  /* Symbol used to separate groups of digits to the left of the decimal
+     point.  */
+  char *mon_thousands_sep;
+  /* Definition of the size of groups of digits to the left of the decimal
+     point.  */
+  char *mon_grouping;
+  /* Sign used to indicate a value >= 0.  */
+  char *positive_sign;
+  /* Sign used to indicate a value < 0.  */
+  char *negative_sign;
+
+  /* For formatting local currency.  */
+  /* Currency symbol (3 characters) followed by separator (1 character).  */
+  char *currency_symbol;
+  /* Number of digits after the decimal point.  */
+  char frac_digits;
+  /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it
+     comes after the number.  */
+  char p_cs_precedes;
+  /* For values >= 0: Position of the sign.  */
+  char p_sign_posn;
+  /* For values >= 0: Placement of spaces between currency symbol, sign, and
+     number.  */
+  char p_sep_by_space;
+  /* For values < 0: 1 if the currency symbol precedes the number, 0 if it
+     comes after the number.  */
+  char n_cs_precedes;
+  /* For values < 0: Position of the sign.  */
+  char n_sign_posn;
+  /* For values < 0: Placement of spaces between currency symbol, sign, and
+     number.  */
+  char n_sep_by_space;
+
+  /* For formatting international currency.  */
+  /* Currency symbol (3 characters) followed by separator (1 character).  */
+  char *int_curr_symbol;
+  /* Number of digits after the decimal point.  */
+  char int_frac_digits;
+  /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it
+     comes after the number.  */
+  char int_p_cs_precedes;
+  /* For values >= 0: Position of the sign.  */
+  char int_p_sign_posn;
+  /* For values >= 0: Placement of spaces between currency symbol, sign, and
+     number.  */
+  char int_p_sep_by_space;
+  /* For values < 0: 1 if the currency symbol precedes the number, 0 if it
+     comes after the number.  */
+  char int_n_cs_precedes;
+  /* For values < 0: Position of the sign.  */
+  char int_n_sign_posn;
+  /* For values < 0: Placement of spaces between currency symbol, sign, and
+     number.  */
+  char int_n_sep_by_space;
+};
+#endif
+
 #if @GNULIB_SETLOCALE@
 # if @REPLACE_SETLOCALE@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
--- m4/locale_h.m4.orig Sun Mar 25 13:20:43 2012
+++ m4/locale_h.m4      Sun Mar 25 13:13:49 2012
@@ -1,4 +1,4 @@
-# locale_h.m4 serial 14
+# locale_h.m4 serial 15
 dnl Copyright (C) 2007, 2009-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,7 +10,8 @@
   dnl once only, before all statements that occur in other macros.
   AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
 
-  dnl Persuade glibc <locale.h> to define locale_t.
+  dnl Persuade glibc <locale.h> to define locale_t and the int_p_*, int_n_*
+  dnl members of 'struct lconv'.
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
   dnl If <stddef.h> is replaced, then <locale.h> must also be replaced.
@@ -21,7 +22,8 @@
     [AC_COMPILE_IFELSE(
        [AC_LANG_PROGRAM(
           [[#include <locale.h>
-            int x = LC_MESSAGES;]],
+            int x = LC_MESSAGES;
+            int y = sizeof (((struct lconv *) 0)->decimal_point);]],
           [[]])],
        [gl_cv_header_locale_h_posix2001=yes],
        [gl_cv_header_locale_h_posix2001=no])])
@@ -54,6 +56,23 @@
   fi
   AC_SUBST([HAVE_XLOCALE_H])
 
+  dnl Check whether 'struct lconv' is well-defined.
+  dnl Bionic libc's 'struct lconv' is just a dummy.
+  AC_CACHE_CHECK([whether struct lconv is properly defined],
+    [gl_cv_sys_struct_lconv_ok],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <locale.h>
+            struct lconv l;
+            int x = sizeof (l.decimal_point);]],
+          [[]])],
+       [gl_cv_sys_struct_lconv_ok=yes],
+       [gl_cv_sys_struct_lconv_ok=no])
+    ])
+  if test $gl_cv_sys_struct_lconv_ok = no; then
+    REPLACE_STRUCT_LCONV=1
+  fi
+
   dnl <locale.h> is always overridden, because of GNULIB_POSIXCHECK.
   gl_NEXT_HEADERS([locale.h])
 
@@ -82,7 +101,8 @@
   GNULIB_SETLOCALE=0;  AC_SUBST([GNULIB_SETLOCALE])
   GNULIB_DUPLOCALE=0;  AC_SUBST([GNULIB_DUPLOCALE])
   dnl Assume proper GNU behavior unless another module says otherwise.
-  HAVE_DUPLOCALE=1;    AC_SUBST([HAVE_DUPLOCALE])
-  REPLACE_SETLOCALE=0; AC_SUBST([REPLACE_SETLOCALE])
-  REPLACE_DUPLOCALE=0; AC_SUBST([REPLACE_DUPLOCALE])
+  HAVE_DUPLOCALE=1;       AC_SUBST([HAVE_DUPLOCALE])
+  REPLACE_SETLOCALE=0;    AC_SUBST([REPLACE_SETLOCALE])
+  REPLACE_DUPLOCALE=0;    AC_SUBST([REPLACE_DUPLOCALE])
+  REPLACE_STRUCT_LCONV=0; AC_SUBST([REPLACE_STRUCT_LCONV])
 ])
--- modules/locale.orig Sun Mar 25 13:20:43 2012
+++ modules/locale      Sun Mar 25 12:46:54 2012
@@ -35,6 +35,7 @@
              -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \
              -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \
              -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \
+             -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \
              -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
              -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
              -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
--- tests/test-locale.c.orig    Sun Mar 25 13:20:44 2012
+++ tests/test-locale.c Sun Mar 25 13:19:10 2012
@@ -38,6 +38,10 @@
 locale_t b = LC_GLOBAL_LOCALE;
 #endif
 
+/* Check that the 'struct lconv' type is defined.  */
+struct lconv l;
+int ls;
+
 /* Check that NULL can be passed through varargs as a pointer type,
    per POSIX 2008.  */
 verify (sizeof NULL == sizeof (void *));
@@ -45,5 +49,33 @@
 int
 main ()
 {
+  /* Check that 'struct lconv' has the ISO C and POSIX specified members.  */
+  ls += sizeof (*l.decimal_point);
+  ls += sizeof (*l.thousands_sep);
+  ls += sizeof (*l.grouping);
+  ls += sizeof (*l.mon_decimal_point);
+  ls += sizeof (*l.mon_thousands_sep);
+  ls += sizeof (*l.mon_grouping);
+  ls += sizeof (*l.positive_sign);
+  ls += sizeof (*l.negative_sign);
+  ls += sizeof (*l.currency_symbol);
+  ls += sizeof (l.frac_digits);
+  ls += sizeof (l.p_cs_precedes);
+  ls += sizeof (l.p_sign_posn);
+  ls += sizeof (l.p_sep_by_space);
+  ls += sizeof (l.n_cs_precedes);
+  ls += sizeof (l.n_sign_posn);
+  ls += sizeof (l.n_sep_by_space);
+  ls += sizeof (*l.int_curr_symbol);
+  ls += sizeof (l.int_frac_digits);
+#if 0
+  ls += sizeof (l.int_p_cs_precedes);
+  ls += sizeof (l.int_p_sign_posn);
+  ls += sizeof (l.int_p_sep_by_space);
+  ls += sizeof (l.int_n_cs_precedes);
+  ls += sizeof (l.int_n_sign_posn);
+  ls += sizeof (l.int_n_sep_by_space);
+#endif
+
   return 0;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]