summaryrefslogtreecommitdiff
path: root/lib/wcwidth.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2018-06-24 16:19:31 +0200
committerBruno Haible <bruno@clisp.org>2018-06-24 16:19:31 +0200
commit7903cdbf6022f3f28a94d484926672e865311905 (patch)
treeeeb583547973a92c3daa3562466d7ce0c23024ae /lib/wcwidth.c
parent58ee14c1ec71f63018db2e8f2d0e3d9cde4f3019 (diff)
downloadgnulib-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.c38
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
{