From cc5eca75540f0750fbc325eab1f82c168564336b Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Tue, 22 Nov 2011 18:31:27 +0100 Subject: [PATCH] Activate our new multibyte implementation. * add implementations for the following multibyte-related functions: btwoc() mblen() mbrlen() mbrtowc() mbsinit() mbtowc() wcrtomb() wcswidth() wctob() wctomb() * the implementation of the above function live in a symbol named __, the above symbol names are defined as a weak alias to the internal ones - TODO: we need to make sure to only invoked the internal functions (i.e. prepended with __) in order to avoid problems with symbol preemption. * deactivate the limited mb implementation we provided before, as well as respective stuff from glibc --- headers/private/libroot/wchar_private.h | 5 ++ src/system/libroot/posix/glibc/stdlib/Jamfile | 3 - src/system/libroot/posix/glibc/wcsmbs/Jamfile | 8 -- src/system/libroot/posix/locale/Jamfile | 5 -- src/system/libroot/posix/wchar/Jamfile | 20 ++++- src/system/libroot/posix/wchar/btowc.c | 33 ++++++++ src/system/libroot/posix/wchar/mblen.c | 32 ++++++++ src/system/libroot/posix/wchar/mbrlen.c | 21 +++++ src/system/libroot/posix/wchar/mbrtowc.cpp | 77 +++++++++++++++++++ src/system/libroot/posix/wchar/mbsinit.c | 16 ++++ src/system/libroot/posix/wchar/mbtowc.c | 26 +++++++ src/system/libroot/posix/wchar/wcrtomb.cpp | 67 ++++++++++++++++ src/system/libroot/posix/wchar/wcswidth.c | 9 ++- src/system/libroot/posix/wchar/wctob.c | 24 ++++++ src/system/libroot/posix/wchar/wctomb.c | 18 +++++ 15 files changed, 342 insertions(+), 22 deletions(-) create mode 100644 src/system/libroot/posix/wchar/btowc.c create mode 100644 src/system/libroot/posix/wchar/mblen.c create mode 100644 src/system/libroot/posix/wchar/mbrlen.c create mode 100644 src/system/libroot/posix/wchar/mbrtowc.cpp create mode 100644 src/system/libroot/posix/wchar/mbsinit.c create mode 100644 src/system/libroot/posix/wchar/mbtowc.c create mode 100644 src/system/libroot/posix/wchar/wcrtomb.cpp create mode 100644 src/system/libroot/posix/wchar/wctob.c create mode 100644 src/system/libroot/posix/wchar/wctomb.c diff --git a/headers/private/libroot/wchar_private.h b/headers/private/libroot/wchar_private.h index 6fc699ff62..b3dc5fea6e 100644 --- a/headers/private/libroot/wchar_private.h +++ b/headers/private/libroot/wchar_private.h @@ -17,11 +17,14 @@ __BEGIN_DECLS extern wint_t __btowc(int); +extern int __mblen(const char *string, size_t maxSize); extern size_t __mbrlen(const char *s, size_t n, mbstate_t *ps); extern size_t __mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps); extern int __mbsinit(const mbstate_t *); extern size_t __mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps); +extern size_t __mbstowcs(wchar_t *pwcs, const char *string, size_t maxSize); +extern int __mbtowc(wchar_t *pwc, const char *string, size_t maxSize); extern size_t __wcrtomb(char *, wchar_t, mbstate_t *); extern wchar_t *__wcscat(wchar_t *, const wchar_t *); @@ -51,6 +54,8 @@ extern long double __wcstold(const wchar_t *, wchar_t **); extern long long __wcstoll(const wchar_t *, wchar_t **, int); extern unsigned long __wcstoul(const wchar_t *, wchar_t **, int); extern unsigned long long __wcstoull(const wchar_t *, wchar_t **, int); +extern size_t __wcstombs(char *string, const wchar_t *pwcs, size_t maxSize); +extern int __wctomb(char *string, wchar_t wchar); extern wchar_t *__wcswcs(const wchar_t *, const wchar_t *); extern int __wcswidth(const wchar_t *, size_t); extern size_t __wcsxfrm(wchar_t *, const wchar_t *, size_t); diff --git a/src/system/libroot/posix/glibc/stdlib/Jamfile b/src/system/libroot/posix/glibc/stdlib/Jamfile index 94e22c7a23..acf6be776c 100644 --- a/src/system/libroot/posix/glibc/stdlib/Jamfile +++ b/src/system/libroot/posix/glibc/stdlib/Jamfile @@ -23,9 +23,7 @@ MergeObject posix_gnu_stdlib.o : lcong48_r.c lrand48.c lrand48_r.c - mblen.c mbstowcs.c - mbtowc.c mrand48.c mrand48_r.c nrand48.c @@ -39,5 +37,4 @@ MergeObject posix_gnu_stdlib.o : strtold.c strtof.c wcstombs.c - wctomb.c ; diff --git a/src/system/libroot/posix/glibc/wcsmbs/Jamfile b/src/system/libroot/posix/glibc/wcsmbs/Jamfile index 54fe9e2a56..b8c4768c2c 100644 --- a/src/system/libroot/posix/glibc/wcsmbs/Jamfile +++ b/src/system/libroot/posix/glibc/wcsmbs/Jamfile @@ -15,16 +15,11 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; MergeObject posix_gnu_wcsmbs.o : - btowc.c - mbrlen.c - mbrtowc.c - mbsinit.c mbsnrtowcs.c mbsrtowcs.c # mbsrtowcs_l.c wcpcpy.c wcpncpy.c - wcrtomb.c wcscasecmp.c # wcscasecmp_l.c wcscat.c @@ -55,10 +50,7 @@ MergeObject posix_gnu_wcsmbs.o : wcstold.c wcstoul.c wcstoull.c -# wcswidth.c wcsxfrm.c - wctob.c -# wcwidth.c wmemchr.c wmemcmp.c wmemcpy.c diff --git a/src/system/libroot/posix/locale/Jamfile b/src/system/libroot/posix/locale/Jamfile index b35c6eea14..f65b3349a0 100644 --- a/src/system/libroot/posix/locale/Jamfile +++ b/src/system/libroot/posix/locale/Jamfile @@ -13,10 +13,5 @@ MergeObject posix_locale.o : localeconv.cpp nl_langinfo.cpp setlocale.cpp - #mb_none.c - #mblen.c - #mbrtowc.c - #mbsinit.c - #wcrtomb.c wctype.cpp ; diff --git a/src/system/libroot/posix/wchar/Jamfile b/src/system/libroot/posix/wchar/Jamfile index 0c52b81011..644a790434 100644 --- a/src/system/libroot/posix/wchar/Jamfile +++ b/src/system/libroot/posix/wchar/Jamfile @@ -1,6 +1,20 @@ SubDir HAIKU_TOP src system libroot posix wchar ; -MergeObject posix_wchar.o : - wcwidth.c - wcswidth.c +UsePrivateHeaders + [ FDirName libroot ] + [ FDirName libroot locale ] +; + +MergeObject posix_wchar.o : + btowc.c + mblen.c + mbrlen.c + mbrtowc.cpp + mbsinit.c + mbtowc.c + wcrtomb.cpp + wcswidth.c + wctob.c + wctomb.c + wcwidth.c ; diff --git a/src/system/libroot/posix/wchar/btowc.c b/src/system/libroot/posix/wchar/btowc.c new file mode 100644 index 0000000000..9ba53fad67 --- /dev/null +++ b/src/system/libroot/posix/wchar/btowc.c @@ -0,0 +1,33 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + + +wint_t +__btowc(int c) +{ + static mbstate_t internalMbState; + char character = (char)c; + wchar_t wc; + + if (c == EOF) + return WEOF; + + if (c == '\0') + return L'\0'; + + { + int byteCount = mbrtowc(&wc, &character, 1, &internalMbState); + + if (byteCount != 1) + return WEOF; + } + + return wc; +} + + +B_DEFINE_WEAK_ALIAS(__btowc, btowc); diff --git a/src/system/libroot/posix/wchar/mblen.c b/src/system/libroot/posix/wchar/mblen.c new file mode 100644 index 0000000000..d582e01ac3 --- /dev/null +++ b/src/system/libroot/posix/wchar/mblen.c @@ -0,0 +1,32 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + + + int +__mblen(const char* s, size_t n) + { + static mbstate_t internalMbState; + int rval; + + if (s == NULL) { + static const mbstate_t initial; + + internalMbState = initial; + + return 0; // we do not support stateful converters + } + + rval = __mbrtowc(NULL, s, n, &internalMbState); + + if (rval == -1 || rval == -2) + return -1; + + return rval; + } + + +B_DEFINE_WEAK_ALIAS(__mblen, mblen); diff --git a/src/system/libroot/posix/wchar/mbrlen.c b/src/system/libroot/posix/wchar/mbrlen.c new file mode 100644 index 0000000000..03873f24cc --- /dev/null +++ b/src/system/libroot/posix/wchar/mbrlen.c @@ -0,0 +1,21 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + + + size_t +__mbrlen(const char* s, size_t n, mbstate_t* ps) + { + if (ps == NULL) { + static mbstate_t internalMbState; + ps = &internalMbState; + } + + return __mbrtowc(NULL, s, n, ps); + } + + +B_DEFINE_WEAK_ALIAS(__mbrlen, mbrlen); diff --git a/src/system/libroot/posix/wchar/mbrtowc.cpp b/src/system/libroot/posix/wchar/mbrtowc.cpp new file mode 100644 index 0000000000..edd26a5c42 --- /dev/null +++ b/src/system/libroot/posix/wchar/mbrtowc.cpp @@ -0,0 +1,77 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include +#include +#include + +#include "LocaleBackend.h" + + +using BPrivate::Libroot::gLocaleBackend; + + +extern "C" size_t +__mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps) +{ + if (ps == NULL) { + static mbstate_t internalMbState; + ps = &internalMbState; + } + + if (s == NULL) + return __mbrtowc(NULL, "", 1, ps); + + if (gLocaleBackend == NULL) { + if (*s == '\0') { + memset(ps, 0, sizeof(mbstate_t)); + + if (pwc != NULL) + *pwc = 0; + + return 0; + } + + /* + * The POSIX locale is active. Since the POSIX locale only contains + * chars 0-127 and those ASCII chars are compatible with the UTF32 + * values used in wint_t, we can just return the byte. + */ + + if (*s < 0) { + // char is non-ASCII + errno = EILSEQ; + return (size_t)-1; + } + + if (pwc != NULL) + *pwc = *s; + + return 1; + } + + size_t lengthUsed; + status_t status + = gLocaleBackend->MultibyteToWchar(pwc, s, n, ps, lengthUsed); + + if (status == B_BAD_INDEX) + return (size_t)-2; + + if (status == B_BAD_DATA) { + errno = EILSEQ; + return (size_t)-1; + } + + if (status != B_OK) { + errno = EINVAL; + return (size_t)-1; + } + + return lengthUsed; +} + + +extern "C" +B_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc); diff --git a/src/system/libroot/posix/wchar/mbsinit.c b/src/system/libroot/posix/wchar/mbsinit.c new file mode 100644 index 0000000000..5a17e7a98e --- /dev/null +++ b/src/system/libroot/posix/wchar/mbsinit.c @@ -0,0 +1,16 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + + + int +__mbsinit(const mbstate_t* ps) + { + return ps == NULL || ps->count == 0; + } + + +B_DEFINE_WEAK_ALIAS(__mbsinit, mbsinit); diff --git a/src/system/libroot/posix/wchar/mbtowc.c b/src/system/libroot/posix/wchar/mbtowc.c new file mode 100644 index 0000000000..e7f411f689 --- /dev/null +++ b/src/system/libroot/posix/wchar/mbtowc.c @@ -0,0 +1,26 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + +#include + + +int +__mbtowc(wchar_t* pwc, const char* s, size_t n) +{ + static mbstate_t internalMbState; + + int result = mbrtowc(pwc, s, n, &internalMbState); + if (result == -2) { + errno = EILSEQ; + result = -1; + } + + return result; +} + + +B_DEFINE_WEAK_ALIAS(__mbtowc, mbtowc); diff --git a/src/system/libroot/posix/wchar/wcrtomb.cpp b/src/system/libroot/posix/wchar/wcrtomb.cpp new file mode 100644 index 0000000000..3ef65e7f2b --- /dev/null +++ b/src/system/libroot/posix/wchar/wcrtomb.cpp @@ -0,0 +1,67 @@ +/* +** Copyright 2011, Oliver Tappe . All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include +#include +#include + +#include "LocaleBackend.h" + + +using BPrivate::Libroot::gLocaleBackend; + + +extern "C" size_t +__wcrtomb(char* s, wchar_t wc, mbstate_t* ps) +{ + if (ps == NULL) { + static mbstate_t internalMbState; + ps = &internalMbState; + } + + if (s == NULL) { + char internalBuffer[MB_LEN_MAX]; + + return __wcrtomb(internalBuffer, L'\0', ps); + } + + if (gLocaleBackend == NULL) { + /* + * The POSIX locale is active. Since the POSIX locale only contains + * chars 0-127 and those ASCII chars are compatible with the UTF32 + * values used in wint_t, we can just return the byte. + */ + + if (wc > 127) { + // char is non-ASCII + errno = EILSEQ; + return (size_t)-1; + } + + *s = char(wc); + + return 1; + } + + size_t lengthUsed; + status_t status = gLocaleBackend->WcharToMultibyte(s, wc, ps, lengthUsed); + + if (status == B_BAD_INDEX) + return (size_t)-2; + if (status == B_BAD_DATA) { + errno = EILSEQ; + return (size_t)-1; + } + if (status != B_OK) { + errno = EINVAL; + return (size_t)-1; + } + + return lengthUsed; +} + + +extern "C" +B_DEFINE_WEAK_ALIAS(__wcrtomb, wcrtomb); diff --git a/src/system/libroot/posix/wchar/wcswidth.c b/src/system/libroot/posix/wchar/wcswidth.c index bf4f2d66c4..367a6fb2dd 100644 --- a/src/system/libroot/posix/wchar/wcswidth.c +++ b/src/system/libroot/posix/wchar/wcswidth.c @@ -1,13 +1,13 @@ /* - * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de + * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de * All rights reserved. Distributed under the terms of the MIT License. */ -#include +#include int -wcswidth(const wchar_t* wcstring, size_t n) +__wcswidth(const wchar_t* wcstring, size_t n) { int width = 0; @@ -21,3 +21,6 @@ wcswidth(const wchar_t* wcstring, size_t n) return width; } + + +B_DEFINE_WEAK_ALIAS(__wcswidth, wcswidth); diff --git a/src/system/libroot/posix/wchar/wctob.c b/src/system/libroot/posix/wchar/wctob.c new file mode 100644 index 0000000000..1537a621c6 --- /dev/null +++ b/src/system/libroot/posix/wchar/wctob.c @@ -0,0 +1,24 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + +#include + + +int +__wctob(wint_t c) +{ + char internalBuffer[MB_LEN_MAX]; + + int32_t byteCount = wcrtomb(internalBuffer, c, NULL); + if (byteCount != 1) + return EOF; + + return (int)(unsigned char)internalBuffer[0]; +} + + +B_DEFINE_WEAK_ALIAS(__wctob, wctob); diff --git a/src/system/libroot/posix/wchar/wctomb.c b/src/system/libroot/posix/wchar/wctomb.c new file mode 100644 index 0000000000..fb78bf33b2 --- /dev/null +++ b/src/system/libroot/posix/wchar/wctomb.c @@ -0,0 +1,18 @@ +/* +** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + +#include + + +int +__wctomb(char* s, wchar_t wc) +{ + static mbstate_t internalMbState; + + return wcrtomb(s, wc, &internalMbState); +} + + +B_DEFINE_WEAK_ALIAS(__wctomb, wctomb);