summaryrefslogtreecommitdiff
path: root/libc/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdlib')
-rw-r--r--libc/stdlib/Makefile6
-rw-r--r--libc/stdlib/stdlib.c133
2 files changed, 139 insertions, 0 deletions
diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile
index 64ae75d18..e69ec4ea8 100644
--- a/libc/stdlib/Makefile
+++ b/libc/stdlib/Makefile
@@ -35,6 +35,12 @@ ifeq ($(HAS_LONG_LONG),true)
MOBJ += llabs.o atoll.o strtoll.o strtoull.o _stdlib_strto_ll.o
endif
+ifeq ($(HAS_WCHAR),true)
+ MOBJ += mblen.o mbtowc.o wctomb.o mbstowcs.o wcstombs.o \
+ _stdlib_mb_cur_max.o
+endif
+
+
MSRC2=atexit.c
MOBJ2=atexit.o on_exit.o __exit_handler.o exit.o
diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c
index 1cd350c31..4c9e8f039 100644
--- a/libc/stdlib/stdlib.c
+++ b/libc/stdlib/stdlib.c
@@ -623,3 +623,136 @@ void ssort (void *base,
#endif
/**********************************************************************/
+/* Multibyte and wchar stuff follows. */
+
+#ifdef __UCLIBC_HAS_WCHAR__
+
+#include <locale.h>
+#include <wchar.h>
+
+/* TODO: clean up the following... */
+
+#if WCHAR_MAX > 0xffffU
+#define UTF_8_MAX_LEN 6
+#else
+#define UTF_8_MAX_LEN 3
+#endif
+
+#define ENCODING (__global_locale.encoding)
+
+#endif
+
+/**********************************************************************/
+#ifdef L__stdlib_mb_cur_max
+
+size_t _stdlib_mb_cur_max(void)
+{
+ return __global_locale.mb_cur_max;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_mblen
+
+#warning implement __CTYPE_HAS_UTF_8_LOCALES!
+#define __CTYPE_HAS_UTF_8_LOCALES
+
+int mblen(register const char *s, size_t n)
+{
+ static mbstate_t state;
+ size_t r;
+
+ if (!s) {
+ state.mask = 0;
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+ return ENCODING == __ctype_encoding_utf8;
+#else
+ return 0;
+#endif
+ }
+
+ if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
+ /* TODO: Should we set an error state? */
+ state.wc = 0xffffU; /* Make sure we're in an error state. */
+ return (size_t) -1; /* TODO: Change error code above? */
+ }
+ return r;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_mbtowc
+
+#warning implement __CTYPE_HAS_UTF_8_LOCALES!
+#define __CTYPE_HAS_UTF_8_LOCALES
+
+int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
+{
+ static mbstate_t state;
+ size_t r;
+
+ if (!s) {
+ state.mask = 0;
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+ return ENCODING == __ctype_encoding_utf8;
+#else
+ return 0;
+#endif
+ }
+
+ if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
+ /* TODO: Should we set an error state? */
+ state.wc = 0xffffU; /* Make sure we're in an error state. */
+ return (size_t) -1; /* TODO: Change error code above? */
+ }
+ return r;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wctomb
+
+#warning implement __CTYPE_HAS_UTF_8_LOCALES!
+#define __CTYPE_HAS_UTF_8_LOCALES
+
+/* Note: We completely ignore state in all currently supported conversions. */
+
+int wctomb(register char *__restrict s, wchar_t swc)
+{
+ return (!s)
+ ?
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+ (ENCODING == __ctype_encoding_utf8)
+#else
+ 0 /* Encoding is stateless. */
+#endif
+ : ((ssize_t) wcrtomb(s, swc, NULL));
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_mbstowcs
+
+size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
+{
+ mbstate_t state;
+
+ state.mask = 0; /* Always start in initial shift state. */
+
+ return mbsrtowcs(pwcs, &s, n, &state);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcstombs
+
+/* Note: We completely ignore state in all currently supported conversions. */
+
+size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
+{
+ return wcsrtombs(s, &pwcs, n, NULL);
+}
+
+#endif
+/**********************************************************************/
+