diff options
author | Bruno Haible <bruno@clisp.org> | 2018-06-24 16:19:31 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2018-06-24 16:19:31 +0200 |
commit | 7903cdbf6022f3f28a94d484926672e865311905 (patch) | |
tree | eeb583547973a92c3daa3562466d7ce0c23024ae /lib/wcwidth.c | |
parent | 58ee14c1ec71f63018db2e8f2d0e3d9cde4f3019 (diff) | |
download | gnulib-7903cdbf6022f3f28a94d484926672e865311905.tar.gz |
mbrtowc, wcwidth: Fix MT-safety bug (regression from 2018-06-23).
* lib/mbrtowc.c (enc_t): New enum type.
(locale_enc, locale_enc_cached): New functions.
(mbrtowc): Eliminate static variables. Use locale_enc_cached instead.
* lib/wcwidth.c (is_locale_utf8, is_locale_utf8_cached): New functions.
(wcwidth): Eliminate static variables. Use is_locale_utf8_cached
instead.
* m4/mbrtowc.m4 (gl_PREREQ_MBRTOWC): Require AC_C_INLINE.
* m4/wcwidth.m4 (gl_PREREQ_WCWIDTH): New macro.
* modules/wcwidth (configure.ac): Invoke it.
Diffstat (limited to 'lib/wcwidth.c')
-rw-r--r-- | lib/wcwidth.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/lib/wcwidth.c b/lib/wcwidth.c index d03a50f3eb..d33b6a9a55 100644 --- a/lib/wcwidth.c +++ b/lib/wcwidth.c @@ -26,28 +26,40 @@ #include "streq.h" #include "uniwidth.h" -int -wcwidth (wchar_t wc) -#undef wcwidth +/* Returns 1 if the current locale is an UTF-8 locale, 0 otherwise. */ +static inline int +is_locale_utf8 (void) { - static int utf8_charset = -1; - static const char *encoding; + const char *encoding = locale_charset (); + return STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0); +} #if GNULIB_WCHAR_SINGLE - if (utf8_charset == -1) +/* When we know that the locale does not change, provide a speedup by + caching the value of is_locale_utf8. */ +static int cached_is_locale_utf8 = -1; +static inline int +is_locale_utf8_cached (void) +{ + if (cached_is_locale_utf8 < 0) + cached_is_locale_utf8 = is_locale_utf8 (); + return cached_is_locale_utf8; +} +#else +/* By default, don't make assumptions, hence no caching. */ +# define is_locale_utf8_cached is_locale_utf8 #endif - { - encoding = locale_charset (); - utf8_charset = STREQ_OPT (encoding, - "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0); - } +int +wcwidth (wchar_t wc) +#undef wcwidth +{ /* In UTF-8 locales, use a Unicode aware width function. */ - if (utf8_charset) + if (is_locale_utf8_cached ()) { /* We assume that in a UTF-8 locale, a wide character is the same as a Unicode character. */ - return uc_width (wc, encoding); + return uc_width (wc, "UTF-8"); } else { |