Add lconv declaration and localeconv(3)

lconv is taken from ndk/sources/android/support/include/locale.h and
matches
bsd/glibc upstream.
Keep old declaration for 32-bits for compatibility.
localeconv.c and deps are taken from openbsd upstream.
Changed strtod.c accordingly.

Change-Id: I9fcc4d15f5674d192950d80edf26f36006cd31b4
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 88da1f3..7b6b1c3 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -14,6 +14,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcpy.c \
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 28806e1..9b29f0d 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -16,6 +16,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcmp.c \
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 9bce065..a3adaa4 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -18,6 +18,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcmp.c \
diff --git a/libc/include/locale.h b/libc/include/locale.h
index b6dbfdb..4efc564 100644
--- a/libc/include/locale.h
+++ b/libc/include/locale.h
@@ -51,12 +51,41 @@
 
 extern char* setlocale(int, const char*);
 
-#if !defined(__LP64__)
-// TODO: LP32 had these bogus declarations but LP64 should have a real struct lconv and localeconv(3).
+#if defined(__LP64__)
+struct lconv {
+    char* decimal_point;
+    char* thousands_sep;
+    char* grouping;
+    char* int_curr_symbol;
+    char* currency_symbol;
+    char* mon_decimal_point;
+    char* mon_thousands_sep;
+    char* mon_grouping;
+    char* positive_sign;
+    char* negative_sign;
+    char  int_frac_digits;
+    char  frac_digits;
+    char  p_cs_precedes;
+    char  p_sep_by_space;
+    char  n_cs_precedes;
+    char  n_sep_by_space;
+    char  p_sign_posn;
+    char  n_sign_posn;
+    /* ISO-C99 */
+    char  int_p_cs_precedes;
+    char  int_p_sep_by_space;
+    char  int_n_cs_precedes;
+    char  int_n_sep_by_space;
+    char  int_p_sign_posn;
+    char  int_n_sign_posn;
+};
+#else
+// Keep old declaration for ILP32 for compatibility
 struct lconv { };
-struct lconv* localeconv(void);
 #endif
 
+struct lconv* localeconv(void);
+
 __END_DECLS
 
 #endif /* _LOCALE_H_ */
diff --git a/libc/include/sys/localedef.h b/libc/include/sys/localedef.h
new file mode 100644
index 0000000..b6b5eb1
--- /dev/null
+++ b/libc/include/sys/localedef.h
@@ -0,0 +1,101 @@
+/*	$OpenBSD: localedef.h,v 1.3 1996/04/21 22:31:47 deraadt Exp $	*/
+/*	$NetBSD: localedef.h,v 1.4 1996/04/09 20:55:31 cgd Exp $	*/
+
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_LOCALEDEF_H_
+#define _SYS_LOCALEDEF_H_
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+typedef struct
+{
+	char *yesexpr;
+	char *noexpr;
+	char *yesstr;
+	char *nostr;
+} _MessagesLocale;
+
+extern const _MessagesLocale *_CurrentMessagesLocale;
+extern const _MessagesLocale  _DefaultMessagesLocale;
+
+
+typedef struct
+{
+	char *int_curr_symbol;
+	char *currency_symbol;
+	char *mon_decimal_point;
+	char *mon_thousands_sep;
+	char *mon_grouping;
+	char *positive_sign;
+	char *negative_sign;
+	char int_frac_digits;
+	char frac_digits;
+	char p_cs_precedes;
+	char p_sep_by_space;
+	char n_cs_precedes;
+	char n_sep_by_space;
+	char p_sign_posn;
+	char n_sign_posn;
+} _MonetaryLocale;
+
+extern const _MonetaryLocale *_CurrentMonetaryLocale;
+extern const _MonetaryLocale  _DefaultMonetaryLocale;
+
+
+typedef struct
+{
+	const char *decimal_point;
+	const char *thousands_sep;
+	const char *grouping;
+} _NumericLocale;
+
+extern const _NumericLocale *_CurrentNumericLocale;
+extern const _NumericLocale  _DefaultNumericLocale;
+
+
+typedef struct {
+	const char *abday[7];
+	const char *day[7];
+	const char *abmon[12];
+	const char *mon[12];
+	const char *am_pm[2];
+	const char *d_t_fmt;
+	const char *d_fmt;
+	const char *t_fmt;
+	const char *t_fmt_ampm;
+} _TimeLocale;
+
+extern const _TimeLocale *_CurrentTimeLocale;
+extern const _TimeLocale  _DefaultTimeLocale;
+
+#endif /* !_SYS_LOCALEDEF_H_ */
diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c
index 0a19446..b39c90e 100644
--- a/libc/stdlib/strtod.c
+++ b/libc/stdlib/strtod.c
@@ -1332,13 +1332,14 @@
 	Bigint *bb1, *bd0;
 	Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */
 
-	CONST char decimal_point = '.';
-#if 0 /* BEGIN android-changed: no localeconv. */
+#if defined(__LP64__) /* BEGIN android-changed: no localeconv for ILP32. */
 #ifndef KR_headers
 	CONST char decimal_point = localeconv()->decimal_point[0];
 #else
 	CONST char decimal_point = '.';
 #endif
+#else
+	CONST char decimal_point = '.';
 #endif /* END android-changed */
 
 	sign = nz0 = nz = 0;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_messages.c b/libc/upstream-openbsd/lib/libc/locale/_def_messages.c
new file mode 100644
index 0000000..1ed653a
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_messages.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: _def_messages.c,v 1.5 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _MessagesLocale _DefaultMessagesLocale =
+{
+	"^[Yy]",
+	"^[Nn]",
+	"yes",
+	"no"
+} ;
+
+const _MessagesLocale *_CurrentMessagesLocale = &_DefaultMessagesLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c b/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c
new file mode 100644
index 0000000..aa92c75
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c
@@ -0,0 +1,30 @@
+/*	$OpenBSD: _def_monetary.c,v 1.4 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <limits.h>
+#include <locale.h>
+
+const _MonetaryLocale _DefaultMonetaryLocale =
+{
+	"",
+	"",
+	"",
+	"",
+	"",
+	"",
+	"",
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX
+};
+
+const _MonetaryLocale *_CurrentMonetaryLocale = &_DefaultMonetaryLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c b/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c
new file mode 100644
index 0000000..6511254
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c
@@ -0,0 +1,17 @@
+/*	$OpenBSD: _def_numeric.c,v 1.4 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _NumericLocale _DefaultNumericLocale =
+{
+	".",
+	"",
+	""
+};
+
+const _NumericLocale *_CurrentNumericLocale = &_DefaultNumericLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_time.c b/libc/upstream-openbsd/lib/libc/locale/_def_time.c
new file mode 100644
index 0000000..75179a6
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_time.c
@@ -0,0 +1,36 @@
+/*	$OpenBSD: _def_time.c,v 1.5 2011/10/09 06:39:53 ajacoutot Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _TimeLocale _DefaultTimeLocale =
+{
+	{
+		"Sun","Mon","Tue","Wed","Thu","Fri","Sat",
+	},
+	{
+		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+		"Friday", "Saturday"
+	},
+	{
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	},
+	{
+		"January", "February", "March", "April", "May", "June", "July",
+		"August", "September", "October", "November", "December"
+	},
+	{
+		"AM", "PM"
+	},
+	"%a %b %e %H:%M:%S %Y",
+	"%m/%d/%y",
+	"%H:%M:%S",
+	"%I:%M:%S %p"
+};
+
+const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/localeconv.c b/libc/upstream-openbsd/lib/libc/locale/localeconv.c
new file mode 100644
index 0000000..989eb4b
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/localeconv.c
@@ -0,0 +1,59 @@
+/*	$OpenBSD: localeconv.c,v 1.5 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+/*
+ * The localeconv() function constructs a struct lconv from the current
+ * monetary and numeric locales.
+ *
+ * Because localeconv() may be called many times (especially by library
+ * routines like printf() & strtod()), the approprate members of the
+ * lconv structure are computed only when the monetary or numeric
+ * locale has been changed.
+ */
+int __mlocale_changed = 1;
+int __nlocale_changed = 1;
+
+/*
+ * Return the current locale conversion.
+ */
+struct lconv *
+localeconv(void)
+{
+    static struct lconv ret;
+
+    if (__mlocale_changed) {
+	/* LC_MONETARY */
+	ret.int_curr_symbol	= _CurrentMonetaryLocale->int_curr_symbol;
+	ret.currency_symbol	= _CurrentMonetaryLocale->currency_symbol;
+	ret.mon_decimal_point	= _CurrentMonetaryLocale->mon_decimal_point;
+	ret.mon_thousands_sep	= _CurrentMonetaryLocale->mon_thousands_sep;
+	ret.mon_grouping	= _CurrentMonetaryLocale->mon_grouping;
+	ret.positive_sign	= _CurrentMonetaryLocale->positive_sign;
+	ret.negative_sign	= _CurrentMonetaryLocale->negative_sign;
+	ret.int_frac_digits	= _CurrentMonetaryLocale->int_frac_digits;
+	ret.frac_digits		= _CurrentMonetaryLocale->frac_digits;
+	ret.p_cs_precedes	= _CurrentMonetaryLocale->p_cs_precedes;
+	ret.p_sep_by_space	= _CurrentMonetaryLocale->p_sep_by_space;
+	ret.n_cs_precedes	= _CurrentMonetaryLocale->n_cs_precedes;
+	ret.n_sep_by_space	= _CurrentMonetaryLocale->n_sep_by_space;
+	ret.p_sign_posn		= _CurrentMonetaryLocale->p_sign_posn;
+	ret.n_sign_posn		= _CurrentMonetaryLocale->n_sign_posn;
+	__mlocale_changed = 0;
+    }
+
+    if (__nlocale_changed) {
+	/* LC_NUMERIC */
+	ret.decimal_point	= (char *) _CurrentNumericLocale->decimal_point;
+	ret.thousands_sep	= (char *) _CurrentNumericLocale->thousands_sep;
+	ret.grouping		= (char *) _CurrentNumericLocale->grouping;
+	__nlocale_changed = 0;
+    }
+
+    return (&ret);
+}