changeset 8569:378e85482afa

Use multithread-safe primitives for determining the decimal point character.
author Bruno Haible <bruno@clisp.org>
date Tue, 27 Mar 2007 20:11:59 +0000
parents 392970b32717
children 4175c39ba7cc
files ChangeLog lib/vasnprintf.c
diffstat 2 files changed, 36 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -127,6 +127,33 @@
 /* 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 @@
 			      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 @@
 			      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)