Use multithread-safe primitives for determining the decimal point character.
authorBruno Haible <bruno@clisp.org>
Tue, 27 Mar 2007 20:11:59 +0000 (20:11 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 27 Mar 2007 20:11:59 +0000 (20:11 +0000)
ChangeLog
lib/vasnprintf.c

index b159f56..79fc2df 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-03-27  Bruno Haible  <bruno@clisp.org>
+
+       Make vasnprintf multithread-safe.
+       * lib/vasnprintf.c (decimal_point_char): New function.
+       (VASNPRINTF): Use it.
+       Suggested by Simon Josefsson.
+
 2007-03-27  Eric Blake  <ebb9@byu.net>
 
        Support sub-second birthtime on cygwin.
index ab82b21..adce608 100644 (file)
@@ -127,6 +127,33 @@ local_wcslen (const wchar_t *s)
 /* Here we need to call the native sprintf, not rpl_sprintf.  */
 #undef sprintf
 
+#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
+/* Determine the decimal-point character according to the current locale.  */
+# ifndef decimal_point_char_defined
+#  define decimal_point_char_defined 1
+static char
+decimal_point_char ()
+{
+  const char *point;
+  /* Determine it in a multithread-safe way.  We know nl_langinfo is
+     multithread-safe on glibc systems, but is not required to be multithread-
+     safe by POSIX.  sprintf(), however, is multithread-safe.  localeconv()
+     is rarely multithread-safe.  */
+#  if HAVE_NL_LANGINFO && __GLIBC__
+  point = nl_langinfo (RADIXCHAR);
+#  elif 1
+  char pointbuf[5];
+  sprintf (pointbuf, "%#.0f", 1.0);
+  point = &pointbuf[1];
+#  else
+  point = localeconv () -> decimal_point;
+#  endif
+  /* The decimal point is always a single byte: either '.' or ','.  */
+  return (point[0] != '\0' ? point[0] : '.');
+}
+# endif
+#endif
+
 CHAR_T *
 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
 {
@@ -510,18 +537,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                              if ((flags & FLAG_ALT)
                                  || mantissa > 0.0L || precision > 0)
                                {
-                                 const char *point;
-                                 /* Prefer nl_langinfo() over localeconv(),
-                                    since the latter is not multithread-
-                                    safe.  */
-#  if HAVE_NL_LANGINFO
-                                 point = nl_langinfo (RADIXCHAR);
-#  else
-                                 point = localeconv () -> decimal_point;
-#  endif
-                                 /* The decimal point is always a single byte:
-                                    either '.' or ','.  */
-                                 *p++ = (point[0] != '\0' ? point[0] : '.');
+                                 *p++ = decimal_point_char ();
                                  /* This loop terminates because we assume
                                     that FLT_RADIX is a power of 2.  */
                                  while (mantissa > 0.0L)
@@ -667,18 +683,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                              if ((flags & FLAG_ALT)
                                  || mantissa > 0.0 || precision > 0)
                                {
-                                 const char *point;
-                                 /* Prefer nl_langinfo() over localeconv(),
-                                    since the latter is not multithread-
-                                    safe.  */
-#  if HAVE_NL_LANGINFO
-                                 point = nl_langinfo (RADIXCHAR);
-#  else
-                                 point = localeconv () -> decimal_point;
-#  endif
-                                 /* The decimal point is always a single byte:
-                                    either '.' or ','.  */
-                                 *p++ = (point[0] != '\0' ? point[0] : '.');
+                                 *p++ = decimal_point_char ();
                                  /* This loop terminates because we assume
                                     that FLT_RADIX is a power of 2.  */
                                  while (mantissa > 0.0)