Fix <wctype.h>.
* Fix the return type of towlower_l/towupper_l.
* Implement wctrans/wctrans_l/towctrans/towctrans_l.
* Move declarations that POSIX says are available from both <wchar.h> and
<wctype.h> to <bits/wctype.h> and include from both POSIX headers.
* Write the missing tests.
Change-Id: I3221da5f3d7e8a2fb0a7619dc724de45f7b55398
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index f2d7861..05e9c90 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -26,11 +26,13 @@
* SUCH DAMAGE.
*/
+#include <wctype.h>
+
#include <ctype.h>
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
-#include <wctype.h>
// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
@@ -85,8 +87,8 @@
wint_t towlower(wint_t wc) { return tolower(wc); }
wint_t towupper(wint_t wc) { return toupper(wc); }
-int towupper_l(int c, locale_t) { return towupper(c); }
-int towlower_l(int c, locale_t) { return towlower(c); }
+wint_t towupper_l(int c, locale_t) { return towupper(c); }
+wint_t towlower_l(int c, locale_t) { return towlower(c); }
wctype_t wctype(const char* property) {
static const char* const properties[WC_TYPE_MAX] = {
@@ -109,3 +111,27 @@
int wcwidth(wchar_t wc) {
return (wc > 0);
}
+
+static wctrans_t wctrans_tolower = wctrans_t(1);
+static wctrans_t wctrans_toupper = wctrans_t(2);
+
+wctrans_t wctrans(const char* name) {
+ if (strcmp(name, "tolower") == 0) return wctrans_tolower;
+ if (strcmp(name, "toupper") == 0) return wctrans_toupper;
+ return 0;
+}
+
+wctrans_t wctrans_l(const char* name, locale_t) {
+ return wctrans(name);
+}
+
+wint_t towctrans(wint_t c, wctrans_t t) {
+ if (t == wctrans_tolower) return towlower(c);
+ if (t == wctrans_toupper) return towupper(c);
+ errno = EINVAL;
+ return 0;
+}
+
+wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {
+ return towctrans(c, t);
+}
diff --git a/libc/include/bits/wctype.h b/libc/include/bits/wctype.h
new file mode 100644
index 0000000..8f32aba
--- /dev/null
+++ b/libc/include/bits/wctype.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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
+ * COPYRIGHT OWNER OR CONTRIBUTORS 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 _BITS_WCTYPE_H_
+#define _BITS_WCTYPE_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef __WINT_TYPE__ wint_t;
+
+int iswalnum(wint_t);
+int iswalpha(wint_t);
+int iswblank(wint_t);
+int iswcntrl(wint_t);
+int iswdigit(wint_t);
+int iswgraph(wint_t);
+int iswlower(wint_t);
+int iswprint(wint_t);
+int iswpunct(wint_t);
+int iswspace(wint_t);
+int iswupper(wint_t);
+int iswxdigit(wint_t);
+
+wint_t towlower(wint_t);
+wint_t towupper(wint_t);
+
+typedef long wctype_t;
+wctype_t wctype(const char*);
+int iswctype(wint_t, wctype_t);
+
+typedef const void* wctrans_t;
+wint_t towctrans(wint_t, wctrans_t);
+wctrans_t wctrans(const char*);
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index f65c988..625097e 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -37,10 +37,10 @@
#include <xlocale.h>
#include <bits/wchar_limits.h>
+#include <bits/wctype.h>
__BEGIN_DECLS
-typedef __WINT_TYPE__ wint_t;
typedef struct {
uint8_t __seq[4];
#ifdef __LP64__
@@ -65,26 +65,11 @@
WC_TYPE_MAX
};
-typedef long wctype_t;
-
#define WEOF ((wint_t)(-1))
extern wint_t btowc(int);
extern int fwprintf(FILE *, const wchar_t *, ...);
extern int fwscanf(FILE *, const wchar_t *, ...);
-extern int iswalnum(wint_t);
-extern int iswalpha(wint_t);
-extern int iswblank(wint_t);
-extern int iswcntrl(wint_t);
-extern int iswdigit(wint_t);
-extern int iswgraph(wint_t);
-extern int iswlower(wint_t);
-extern int iswprint(wint_t);
-extern int iswpunct(wint_t);
-extern int iswspace(wint_t);
-extern int iswupper(wint_t);
-extern int iswxdigit(wint_t);
-extern int iswctype(wint_t, wctype_t);
extern wint_t fgetwc(FILE *);
extern wchar_t *fgetws(wchar_t *, int, FILE *);
extern wint_t fputwc(wchar_t, FILE *);
@@ -101,8 +86,6 @@
extern wint_t putwchar(wchar_t);
extern int swprintf(wchar_t *, size_t, const wchar_t *, ...);
extern int swscanf(const wchar_t *, const wchar_t *, ...);
-extern wint_t towlower(wint_t);
-extern wint_t towupper(wint_t);
extern wint_t ungetwc(wint_t, FILE *);
extern int vfwprintf(FILE*, const wchar_t*, va_list);
extern int vfwscanf(FILE*, const wchar_t*, va_list);
@@ -145,7 +128,6 @@
extern int wcswidth(const wchar_t *, size_t);
extern size_t wcsxfrm(wchar_t *, const wchar_t *, size_t);
extern int wctob(wint_t);
-extern wctype_t wctype(const char *);
extern int wcwidth(wchar_t);
extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
extern int wmemcmp(const wchar_t *, const wchar_t *, size_t);
@@ -168,10 +150,6 @@
extern size_t wcslcat(wchar_t*, const wchar_t*, size_t);
extern size_t wcslcpy(wchar_t*, const wchar_t*, size_t);
-typedef void *wctrans_t;
-extern wint_t towctrans(wint_t, wctrans_t) __UNAVAILABLE;
-extern wctrans_t wctrans(const char*) __UNAVAILABLE;
-
#if __POSIX_VISIBLE >= 200809
FILE* open_wmemstream(wchar_t**, size_t*);
wchar_t* wcsdup(const wchar_t*);
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index 1a4a05e..12ef7cd 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -31,25 +31,31 @@
#include <wchar.h>
+#include <bits/wctype.h>
+
__BEGIN_DECLS
-extern int iswalnum_l(wint_t, locale_t);
-extern int iswalpha_l(wint_t, locale_t);
-extern int iswblank_l(wint_t, locale_t);
-extern int iswcntrl_l(wint_t, locale_t);
-extern int iswdigit_l(wint_t, locale_t);
-extern int iswgraph_l(wint_t, locale_t);
-extern int iswlower_l(wint_t, locale_t);
-extern int iswprint_l(wint_t, locale_t);
-extern int iswpunct_l(wint_t, locale_t);
-extern int iswspace_l(wint_t, locale_t);
-extern int iswupper_l(wint_t, locale_t);
-extern int iswxdigit_l(wint_t, locale_t);
-extern int towlower_l(int, locale_t);
-extern int towupper_l(int, locale_t);
+int iswalnum_l(wint_t, locale_t);
+int iswalpha_l(wint_t, locale_t);
+int iswblank_l(wint_t, locale_t);
+int iswcntrl_l(wint_t, locale_t);
+int iswdigit_l(wint_t, locale_t);
+int iswgraph_l(wint_t, locale_t);
+int iswlower_l(wint_t, locale_t);
+int iswprint_l(wint_t, locale_t);
+int iswpunct_l(wint_t, locale_t);
+int iswspace_l(wint_t, locale_t);
+int iswupper_l(wint_t, locale_t);
+int iswxdigit_l(wint_t, locale_t);
-extern int iswctype_l(wint_t, wctype_t, locale_t);
-extern wctype_t wctype_l(const char*, locale_t);
+wint_t towlower_l(int, locale_t);
+wint_t towupper_l(int, locale_t);
+
+wint_t towctrans_l(wint_t, wctrans_t, locale_t);
+wctrans_t wctrans_l(const char*, locale_t);
+
+wctype_t wctype_l(const char*, locale_t);
+int iswctype_l(wint_t, wctype_t, locale_t);
__END_DECLS
diff --git a/libc/libc.arm.brillo.map b/libc/libc.arm.brillo.map
index a1373d8..6998cab 100644
--- a/libc/libc.arm.brillo.map
+++ b/libc/libc.arm.brillo.map
@@ -1291,6 +1291,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 4e69bf1..8628ed1 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1291,6 +1291,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 7ea74a6..c853f73 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1213,6 +1213,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 8d1a1f9..1ed2977 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1316,6 +1316,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.mips.brillo.map b/libc/libc.mips.brillo.map
index aac1d8c..f42f5aa 100644
--- a/libc/libc.mips.brillo.map
+++ b/libc/libc.mips.brillo.map
@@ -1275,6 +1275,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index e514aa1..439c855 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1275,6 +1275,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 7ea74a6..c853f73 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1213,6 +1213,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.x86.brillo.map b/libc/libc.x86.brillo.map
index f14861d..b1ba988 100644
--- a/libc/libc.x86.brillo.map
+++ b/libc/libc.x86.brillo.map
@@ -1273,6 +1273,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index f6b6ea1..bab1737 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1273,6 +1273,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 7ea74a6..c853f73 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1213,6 +1213,10 @@
sigrelse;
sigset;
sync_file_range;
+ towctrans;
+ towctrans_l;
+ wctrans;
+ wctrans_l;
} LIBC_N;
LIBC_PRIVATE {