about summary refs log tree commit diff
path: root/stdlib
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-03-14 21:12:06 +0000
committerUlrich Drepper <drepper@redhat.com>2004-03-14 21:12:06 +0000
commitccadf7b5346a3e21c692dfcbfcf38a63433bc36a (patch)
treea1e826af3345eee581925387513b1b6c76629c31 /stdlib
parent3bc9b83f49805969b7d139b52ef6b003e5136354 (diff)
downloadglibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.tar.gz
glibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.tar.xz
glibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.zip
Update.
2004-03-14  Ulrich Drepper  <drepper@redhat.com>

	Make the non-_l functions wrappers around the _l functions.
	* include/monetary.h: Declare __vstrmon_l.
	* include/string.h: Add libc_hidden_proto for __strcoll_l and
	__strxfrm_l.
	* include/time.h: Define ptime_locale_status.  Declare
	__strptime_internal.
	* include/wchar.h: Add libc_hidden_proto for __wcscoll_l and
	__wcsxfrm_l.
	* stdlib/strfmon.c: Move the code to strfmon_l.c.  Add little
	wrapper around __vstrfmon_l.
	* stdlib/strfmon_l.c: Add real implementation.  Split into new
	function __vstrfmon_l to allow calling it from strfmon.
	* stdlib/strtod.c: Move real code to strtod_l.c and add wrapper.
	* stdlib/strtod_l.c: Add real implementation.
	* stdlib/strtof.c: Adjust to changed strtod.c.
	* stdlib/strtof_l.c: Include strtod_l.c now.
	* stdlib/strtold.c: New file.
	* stdlib/strtold_l.c: Removed.
	* string/strcoll.c: Move real code to strcoll_l.c: Add wrapper.
	* string/strcoll_l.c: Add real implementation.
	* string/strxfrm.c: Move real code to strxfrm_l.c: Add wrapper.
	* string/strxfrm_l.c: Add real implementation.
	* sysdeps/generic/strtol.c: Move real implementation to strtol_l.c.
	Add wrappers.
	* sysdeps/generic/strtol_l.c: Add real implementation.
	* sysdeps/generic/strtold.c: Removed.
	* sysdeps/generic/strtold_l.c: New file.
	* sysdeps/generic/strtoll_l.c: Include strtol_l.c now.  Adjust
	#defines.
	* sysdeps/generic/strtoul_l.c: Likewise.
	* sysdeps/generic/strtoull_l.c: Likewise.
	* sysdeps/generic/wcstol_l.c: Likewise.
	* sysdeps/generic/wcstoll_l.c: Likewise.
	* sysdeps/generic/wcstoul_l.c: Likewise.
	* sysdeps/generic/wcstoull_l.c: Likewise.
	* sysdeps/ieee754/ldbl-128/strtold.c: Removed.
	* sysdeps/ieee754/ldbl-128/strtold_l.c: New file.
	* sysdeps/ieee754/ldbl-96/strtold.c: Removed.
	* sysdeps/ieee754/ldbl-96/strtold_l.c: New file.
	* sysdeps/m68k/strtold.c: Removed.
	* sysdeps/m68k/strtold_l.c: New file.
	* time/strftime.c: Move real code to strftime_l.c.  Add wrapper.
	* time/strftime_l.c: Add real implementation.
	* time/strptime.c: Move real code to strptime_l.c.  Add wrapper.
	* time/strptime_l.c: Add real implementation.
	* time/wcsftime.c: Simplify since only wrappers are defined in
	strftime.c.
	* time/wcsftime_l.c: Include strftime_l.c.
	* wcsmbs/wcscoll.c: Simplify since the file is not used by wcscoll_l.c
	anymore.
	* wcsmbs/wcscoll_l.c: Include strcoll_l.c.
	* wcsmbs/wcsxfrm.c: Simplify since the file is not used by wcsxfrm_l.c
	anymore.
	* wcsmbs/wcsxfrm_l.c: Include strxfrm_l.c.
	* wcsmbs/wcstod.c: Prepare to include new strtod.c.
	* wcsmbs/wcstod_l.c: Include strtod_l.c.
	* wcsmbs/wcstof.c: Prepare to include new strtof.c.
	* wcsmbs/wcstof_l.c: Include strtof_l.c.
	* wcsmbs/wcstold.c: Prepare to include new strtold.c.
	* wcsmbs/wcstold_l.c: Include strtold_l.c.

	* locale/uselocale.c: Use _NL_CURRENT_LOCALE instead of __libc_tsd_get.

	* sysdeps/generic/strcasecmp.c: Optimize a bit.  It's better to get
	a reference to the current locale and then use the _l functions.
	* sysdeps/generic/strncase.c: Likewise.
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/strfmon.c632
-rw-r--r--stdlib/strfmon_l.c636
-rw-r--r--stdlib/strtod.c1560
-rw-r--r--stdlib/strtod_l.c1551
-rw-r--r--stdlib/strtof.c37
-rw-r--r--stdlib/strtof_l.c28
-rw-r--r--stdlib/strtold.c35
-rw-r--r--stdlib/strtold_l.c53
8 files changed, 2282 insertions, 2250 deletions
diff --git a/stdlib/strfmon.c b/stdlib/strfmon.c
index b17dc9823c..b11f95c9ac 100644
--- a/stdlib/strfmon.c
+++ b/stdlib/strfmon.c
@@ -19,645 +19,21 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <ctype.h>
-#include <errno.h>
-#include <langinfo.h>
-#include <locale.h>
 #include <monetary.h>
-#ifdef USE_IN_LIBIO
-# include "../libio/libioP.h"
-# include "../libio/strfile.h"
-#endif
-#include <printf.h>
 #include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include "../locale/localeinfo.h"
+#include <locale/localeinfo.h>
 
 
-#define out_char(Ch)							      \
-  do {									      \
-    if (dest >= s + maxsize - 1)					      \
-      {									      \
-	__set_errno (E2BIG);						      \
-	va_end (ap);							      \
-	return -1;							      \
-      }									      \
-    *dest++ = (Ch);							      \
-  } while (0)
-
-#define out_string(String)						      \
-  do {									      \
-    const char *_s = (String);						      \
-    while (*_s)								      \
-      out_char (*_s++);							      \
-  } while (0)
-
-#define out_nstring(String, N)						      \
-  do {									      \
-    int _n = (N);							      \
-    const char *_s = (String);						      \
-    while (_n-- > 0)							      \
-      out_char (*_s++);							      \
-  } while (0)
-
-#define to_digit(Ch) ((Ch) - '0')
-
-
-/* We use this code also for the extended locale handling where the
-   function gets as an additional argument the locale which has to be
-   used.  To access the values we have to redefine the _NL_CURRENT
-   macro.  */
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# undef _NL_CURRENT
-# define _NL_CURRENT(category, item) \
-  (current->values[_NL_ITEM_INDEX (item)].string)
-#endif
-
-extern int __printf_fp (FILE *, const struct printf_info *,
-			const void *const *);
-libc_hidden_proto (__printf_fp)
-/* This function determines the number of digit groups in the output.
-   The definition is in printf_fp.c.  */
-extern unsigned int __guess_grouping (unsigned int intdig_max,
-				      const char *grouping, wchar_t sepchar);
-
-
-/* We have to overcome some problems with this implementation.  On the
-   one hand the strfmon() function is specified in XPG4 and of course
-   it has to follow this.  But on the other hand POSIX.2 specifies
-   some information in the LC_MONETARY category which should be used,
-   too.  Some of the information contradicts the information which can
-   be specified in format string.  */
-#ifndef USE_IN_EXTENDED_LOCALE_MODEL
 ssize_t
 strfmon (char *s, size_t maxsize, const char *format, ...)
-#else
-ssize_t
-__strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...)
-#endif
 {
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-  struct locale_data *current = loc->__locales[LC_MONETARY];
-#endif
-#ifdef USE_IN_LIBIO
-  _IO_strfile f;
-# ifdef _IO_MTSAFE_IO
-  _IO_lock_t lock;
-# endif
-#else
-  FILE f;
-#endif
-  struct printf_info info;
-  va_list ap;			/* Scan through the varargs.  */
-  char *dest;			/* Pointer so copy the output.  */
-  const char *fmt;		/* Pointer that walks through format.  */
+  va_list ap;
 
   va_start (ap, format);
 
-  dest = s;
-  fmt = format;
-
-  /* Loop through the format-string.  */
-  while (*fmt != '\0')
-    {
-      /* The floating-point value to output.  */
-      union
-      {
-	double dbl;
-	__long_double_t ldbl;
-      }
-      fpnum;
-      int int_format;
-      int print_curr_symbol;
-      int left_prec;
-      int left_pad;
-      int right_prec;
-      int group;
-      char pad;
-      int is_long_double;
-      int p_sign_posn;
-      int n_sign_posn;
-      int sign_posn;
-      int other_sign_posn;
-      int left;
-      int is_negative;
-      int sep_by_space;
-      int other_sep_by_space;
-      int cs_precedes;
-      int other_cs_precedes;
-      const char *sign_string;
-      const char *other_sign_string;
-      int done;
-      const char *currency_symbol;
-      size_t currency_symbol_len;
-      int width;
-      char *startp;
-      const void *ptr;
-      char space_char;
-
-      /* Process all character which do not introduce a format
-	 specification.  */
-      if (*fmt != '%')
-	{
-	  out_char (*fmt++);
-	  continue;
-	}
-
-      /* "%%" means a single '%' character.  */
-      if (fmt[1] == '%')
-	{
-	  out_char (*++fmt);
-	  ++fmt;
-	  continue;
-	}
-
-      /* Defaults for formatting.  */
-      int_format = 0;			/* Use international curr. symbol */
-      print_curr_symbol = 1;		/* Print the currency symbol.  */
-      left_prec = -1;			/* No left precision specified.  */
-      right_prec = -1;			/* No right precision specified.  */
-      group = 1;			/* Print digits grouped.  */
-      pad = ' ';			/* Fill character is <SP>.  */
-      is_long_double = 0;		/* Double argument by default.  */
-      p_sign_posn = -1;			/* This indicates whether the */
-      n_sign_posn = -1;			/* '(' flag is given.  */
-      width = -1;			/* No width specified so far.  */
-      left = 0;				/* Right justified by default.  */
-
-      /* Parse group characters.  */
-      while (1)
-	{
-	  switch (*++fmt)
-	    {
-	    case '=':			/* Set fill character.  */
-	      pad = *++fmt;
-	      if (pad == '\0')
-		{
-		  /* Premature EOS.  */
-		  __set_errno (EINVAL);
-		  va_end (ap);
-		  return -1;
-		}
-	      continue;
-	    case '^':			/* Don't group digits.  */
-	      group = 0;
-	      continue;
-	    case '+':			/* Use +/- for sign of number.  */
-	      if (n_sign_posn != -1)
-		{
-		  __set_errno (EINVAL);
-		  va_end (ap);
-		  return -1;
-		}
-	      p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN);
-	      n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN);
-	      continue;
-	    case '(':			/* Use ( ) for negative sign.  */
-	      if (n_sign_posn != -1)
-		{
-		  __set_errno (EINVAL);
-		  va_end (ap);
-		  return -1;
-		}
-	      p_sign_posn = 0;
-	      n_sign_posn = 0;
-	      continue;
-	    case '!':			/* Don't print the currency symbol.  */
-	      print_curr_symbol = 0;
-	      continue;
-	    case '-':			/* Print left justified.  */
-	      left = 1;
-	      continue;
-	    default:
-	      /* Will stop the loop.  */;
-	    }
-	  break;
-	}
-
-      if (isdigit (*fmt))
-	{
-	  /* Parse field width.  */
-	  width = to_digit (*fmt);
-
-	  while (isdigit (*++fmt))
-	    {
-	      width *= 10;
-	      width += to_digit (*fmt);
-	    }
-
-	  /* If we don't have enough room for the demanded width we
-	     can stop now and return an error.  */
-	  if (dest + width >= s + maxsize)
-	    {
-	      __set_errno (E2BIG);
-	      va_end (ap);
-	      return -1;
-	    }
-	}
-
-      /* Recognize left precision.  */
-      if (*fmt == '#')
-	{
-	  if (!isdigit (*++fmt))
-	    {
-	      __set_errno (EINVAL);
-	      va_end (ap);
-	      return -1;
-	    }
-	  left_prec = to_digit (*fmt);
-
-	  while (isdigit (*++fmt))
-	    {
-	      left_prec *= 10;
-	      left_prec += to_digit (*fmt);
-	    }
-	}
-
-      /* Recognize right precision.  */
-      if (*fmt == '.')
-	{
-	  if (!isdigit (*++fmt))
-	    {
-	      __set_errno (EINVAL);
-	      va_end (ap);
-	      return -1;
-	    }
-	  right_prec = to_digit (*fmt);
-
-	  while (isdigit (*++fmt))
-	    {
-	      right_prec *= 10;
-	      right_prec += to_digit (*fmt);
-	    }
-	}
-
-      /* Handle modifier.  This is an extension.  */
-      if (*fmt == 'L')
-	{
-	  ++fmt;
-	  is_long_double = 1;
-	}
-
-      /* Handle format specifier.  */
-      char int_symbol[4];
-      switch (*fmt++)
-	{
-	case 'i': {		/* Use international currency symbol.  */
-	  const char *int_curr_symbol;
-
-	  int_curr_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
-	  strncpy(int_symbol, int_curr_symbol, 3);
-	  int_symbol[3] = '\0';
-
-	  currency_symbol_len = 3;
-	  currency_symbol = &int_symbol[0];
-	  space_char = int_curr_symbol[3];
-	  int_format = 1;
-	  break;
-	}
-	case 'n':		/* Use national currency symbol.  */
-	  currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL);
-	  currency_symbol_len = strlen (currency_symbol);
-	  space_char = ' ';
-	  int_format = 0;
-	  break;
-	default:		/* Any unrecognized format is an error.  */
-	  __set_errno (EINVAL);
-	  va_end (ap);
-	  return -1;
-	}
-
-      /* If not specified by the format string now find the values for
-	 the format specification.  */
-      if (p_sign_posn == -1)
-	p_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SIGN_POSN : P_SIGN_POSN);
-      if (n_sign_posn == -1)
-	n_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SIGN_POSN : N_SIGN_POSN);
-
-      if (right_prec == -1)
-	{
-	  right_prec = *_NL_CURRENT (LC_MONETARY, int_format ? INT_FRAC_DIGITS : FRAC_DIGITS);
-
-	  if (right_prec == CHAR_MAX)
-	    right_prec = 2;
-	}
-
-      /* If we have to print the digits grouped determine how many
-	 extra characters this means.  */
-      if (group && left_prec != -1)
-	left_prec += __guess_grouping (left_prec,
-				       _NL_CURRENT (LC_MONETARY, MON_GROUPING),
-				       *_NL_CURRENT (LC_MONETARY,
-						     MON_THOUSANDS_SEP));
-
-      /* Now it's time to get the value.  */
-      if (is_long_double == 1)
-	{
-	  fpnum.ldbl = va_arg (ap, long double);
-	  is_negative = fpnum.ldbl < 0;
-	  if (is_negative)
-	    fpnum.ldbl = -fpnum.ldbl;
-	}
-      else
-	{
-	  fpnum.dbl = va_arg (ap, double);
-	  is_negative = fpnum.dbl < 0;
-	  if (is_negative)
-	    fpnum.dbl = -fpnum.dbl;
-	}
-
-      /* We now know the sign of the value and can determine the format.  */
-      if (is_negative)
-	{
-	  sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
-	  /* If the locale does not specify a character for the
-	     negative sign we use a '-'.  */
-	  if (*sign_string == '\0')
-	    sign_string = (const char *) "-";
-	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
-	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
-	  sign_posn = n_sign_posn;
-
-	  other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
-	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
-	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
-	  other_sign_posn = p_sign_posn;
-	}
-      else
-	{
-	  sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
-	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
-	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
-	  sign_posn = p_sign_posn;
-
-	  other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
-	  if (*other_sign_string == '\0')
-	    other_sign_string = (const char *) "-";
-	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
-	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
-	  other_sign_posn = n_sign_posn;
-	}
-
-      /* Set default values for unspecified information.  */
-      if (cs_precedes != 0)
-	cs_precedes = 1;
-      if (other_cs_precedes != 0)
-	other_cs_precedes = 1;
-      if (sep_by_space == CHAR_MAX)
-	sep_by_space = 0;
-      if (other_sep_by_space == CHAR_MAX)
-	other_sep_by_space = 0;
-      if (sign_posn == CHAR_MAX)
-	sign_posn = 1;
-      if (other_sign_posn == CHAR_MAX)
-	other_sign_posn = 1;
-
-      /* Check for degenerate cases */
-      if (sep_by_space == 2)
-	{
-	  if (sign_posn == 0 ||
-	      (sign_posn == 1 && !cs_precedes) ||
-	      (sign_posn == 2 && cs_precedes))
-	    /* sign and symbol are not adjacent, so no separator */
-	    sep_by_space = 0;
-	}
-      if (other_sep_by_space == 2)
-	{
-	  if (other_sign_posn == 0 ||
-	      (other_sign_posn == 1 && !other_cs_precedes) ||
-	      (other_sign_posn == 2 && other_cs_precedes))
-	    /* sign and symbol are not adjacent, so no separator */
-	    other_sep_by_space = 0;
-	}
-
-      /* Set the left precision and padding needed for alignment */
-      if (left_prec == -1)
-	{
-	  left_prec = 0;
-	  left_pad = 0;
-	}
-      else
-	{
-	  /* Set left_pad to number of spaces needed to align positive
-	     and negative formats */
-
-	  int left_bytes = 0;
-	  int other_left_bytes = 0;
-
-	  /* Work out number of bytes for currency string and separator
-	     preceding the value */
-	  if (cs_precedes)
-	    {
-	      left_bytes += currency_symbol_len;
-	      if (sep_by_space != 0)
-		++left_bytes;
-	    }
-
-	  if (other_cs_precedes)
-	    {
-	      other_left_bytes += currency_symbol_len;
-	      if (other_sep_by_space != 0)
-		++other_left_bytes;
-	    }
-
-	  /* Work out number of bytes for the sign (or left parenthesis)
-	     preceding the value */
-	  if (sign_posn == 0 && is_negative)
-	    ++left_bytes;
-	  else if (sign_posn == 1)
-	    left_bytes += strlen (sign_string);
-	  else if (cs_precedes && (sign_posn == 3 || sign_posn == 4))
-	    left_bytes += strlen (sign_string);
-
-	  if (other_sign_posn == 0 && !is_negative)
-	    ++other_left_bytes;
-	  else if (other_sign_posn == 1)
-	    other_left_bytes += strlen (other_sign_string);
-	  else if (other_cs_precedes &&
-		   (other_sign_posn == 3 || other_sign_posn == 4))
-	    other_left_bytes += strlen (other_sign_string);
-
-	  /* Compare the number of bytes preceding the value for
-	     each format, and set the padding accordingly */
-	  if (other_left_bytes > left_bytes)
-	    left_pad = other_left_bytes - left_bytes;
-	  else
-	    left_pad = 0;
-	}
-
-      /* Perhaps we'll someday make these things configurable so
-	 better start using symbolic names now.  */
-#define left_paren '('
-#define right_paren ')'
-
-      startp = dest;		/* Remember start so we can compute length.  */
-
-      while (left_pad-- > 0)
-	out_char (' ');
-
-      if (sign_posn == 0 && is_negative)
-	out_char (left_paren);
-
-      if (cs_precedes)
-	{
-	  if (sign_posn != 0 && sign_posn != 2 && sign_posn != 4
-	      && sign_posn != 5)
-	    {
-	      out_string (sign_string);
-	      if (sep_by_space == 2)
-		out_char (' ');
-	    }
-
-	  if (print_curr_symbol)
-	    {
-	      out_string (currency_symbol);
-
-	      if (sign_posn == 4)
-		{
-		  if (sep_by_space == 2)
-		    out_char (space_char);
-		  out_string (sign_string);
-		  if (sep_by_space == 1)
-		    /* POSIX.2 and SUS are not clear on this case, but C99
-		       says a space follows the adjacent-symbol-and-sign */
-		    out_char (' ');
-		}
-	      else
-		if (sep_by_space == 1)
-		  out_char (space_char);
-	    }
-	}
-      else
-	if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3
-	    && sign_posn != 4 && sign_posn != 5)
-	  out_string (sign_string);
-
-      /* Print the number.  */
-#ifdef USE_IN_LIBIO
-# ifdef _IO_MTSAFE_IO
-      f._sbf._f._lock = &lock;
-# endif
-      INTUSE(_IO_init) ((_IO_FILE *) &f, 0);
-      _IO_JUMPS ((struct _IO_FILE_plus *) &f) = &_IO_str_jumps;
-      INTUSE(_IO_str_init_static) ((_IO_strfile *) &f, dest,
-				   (s + maxsize) - dest, dest);
-#else
-      memset ((void *) &f, 0, sizeof (f));
-      f.__magic = _IOMAGIC;
-      f.__mode.__write = 1;
-      /* The buffer size is one less than MAXLEN
-	 so we have space for the null terminator.  */
-      f.__bufp = f.__buffer = (char *) dest;
-      f.__bufsize = (s + maxsize) - dest;
-      f.__put_limit = f.__buffer + f.__bufsize;
-      f.__get_limit = f.__buffer;
-      /* After the buffer is full (MAXLEN characters have been written),
-	 any more characters written will go to the bit bucket.  */
-      f.__room_funcs = __default_room_functions;
-      f.__io_funcs.__write = NULL;
-      f.__seen = 1;
-#endif
-      /* We clear the last available byte so we can find out whether
-	 the numeric representation is too long.  */
-      s[maxsize - 1] = '\0';
-
-      info.prec = right_prec;
-      info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
-      info.spec = 'f';
-      info.is_long_double = is_long_double;
-      info.is_short = 0;
-      info.is_long = 0;
-      info.alt = 0;
-      info.space = 0;
-      info.left = 0;
-      info.showsign = 0;
-      info.group = group;
-      info.pad = pad;
-      info.extra = 1;		/* This means use values from LC_MONETARY.  */
-      info.wide = 0;
-
-      ptr = &fpnum;
-      done = __printf_fp ((FILE *) &f, &info, &ptr);
-      if (done < 0)
-	{
-	  va_end (ap);
-	  return -1;
-	}
-
-      if (s[maxsize - 1] != '\0')
-	{
-	  __set_errno (E2BIG);
-	  return -1;
-	}
-
-      dest += done;
-
-      if (!cs_precedes)
-	{
-	  if (sign_posn == 3)
-	    {
-	      if (sep_by_space == 1)
-		out_char (' ');
-	      out_string (sign_string);
-	    }
-
-	  if (print_curr_symbol)
-	    {
-	      if ((sign_posn == 3 && sep_by_space == 2)
-		  || (sign_posn == 4 && sep_by_space == 1)
-		  || (sign_posn == 2 && sep_by_space == 1)
-		  || (sign_posn == 1 && sep_by_space == 1)
-		  || (sign_posn == 0 && sep_by_space == 1))
-		out_char (space_char);
-	      out_nstring (currency_symbol, currency_symbol_len);
-	      if (sign_posn == 4)
-		{
-		  if (sep_by_space == 2)
-		    out_char (' ');
-		  out_string (sign_string);
-		}
-	    }
-	}
-
-      if (sign_posn == 2)
-	{
-	  if (sep_by_space == 2)
-	    out_char (' ');
-	  out_string (sign_string);
-	}
-
-      if (sign_posn == 0 && is_negative)
-	out_char (right_paren);
-
-      /* Now test whether the output width is filled.  */
-      if (dest - startp < width)
-	{
-	  if (left)
-	    /* We simply have to fill using spaces.  */
-	    do
-	      out_char (' ');
-	    while (dest - startp < width);
-	  else
-	    {
-	      int dist = width - (dest - startp);
-	      char *cp;
-	      for (cp = dest - 1; cp >= startp; --cp)
-		cp[dist] = cp[0];
-
-	      dest += dist;
-
-	      do
-		startp[--dist] = ' ';
-	      while (dist > 0);
-	    }
-	}
-    }
-
-  /* Terminate the string.  */
-  *dest = '\0';
+  ssize_t res = __vstrfmon_l (s, maxsize, _NL_CURRENT_LOCALE, format, ap);
 
   va_end (ap);
 
-  return dest - s;
+  return res;
 }
diff --git a/stdlib/strfmon_l.c b/stdlib/strfmon_l.c
index b0c82a337e..90076afc45 100644
--- a/stdlib/strfmon_l.c
+++ b/stdlib/strfmon_l.c
@@ -1,5 +1,5 @@
 /* Formatting a monetary value according to the given locale.
-   Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -18,7 +18,637 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
-#include <strfmon.c>
+#include <ctype.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <monetary.h>
+#ifdef USE_IN_LIBIO
+# include "../libio/libioP.h"
+# include "../libio/strfile.h"
+#endif
+#include <printf.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "../locale/localeinfo.h"
 
+
+#define out_char(Ch)							      \
+  do {									      \
+    if (dest >= s + maxsize - 1)					      \
+      {									      \
+	__set_errno (E2BIG);						      \
+	va_end (ap);							      \
+	return -1;							      \
+      }									      \
+    *dest++ = (Ch);							      \
+  } while (0)
+
+#define out_string(String)						      \
+  do {									      \
+    const char *_s = (String);						      \
+    while (*_s)								      \
+      out_char (*_s++);							      \
+  } while (0)
+
+#define out_nstring(String, N)						      \
+  do {									      \
+    int _n = (N);							      \
+    const char *_s = (String);						      \
+    while (_n-- > 0)							      \
+      out_char (*_s++);							      \
+  } while (0)
+
+#define to_digit(Ch) ((Ch) - '0')
+
+
+/* We use this code also for the extended locale handling where the
+   function gets as an additional argument the locale which has to be
+   used.  To access the values we have to redefine the _NL_CURRENT
+   macro.  */
+#undef _NL_CURRENT
+#define _NL_CURRENT(category, item) \
+  (current->values[_NL_ITEM_INDEX (item)].string)
+
+extern int __printf_fp (FILE *, const struct printf_info *,
+			const void *const *);
+libc_hidden_proto (__printf_fp)
+/* This function determines the number of digit groups in the output.
+   The definition is in printf_fp.c.  */
+extern unsigned int __guess_grouping (unsigned int intdig_max,
+				      const char *grouping, wchar_t sepchar);
+
+
+/* We have to overcome some problems with this implementation.  On the
+   one hand the strfmon() function is specified in XPG4 and of course
+   it has to follow this.  But on the other hand POSIX.2 specifies
+   some information in the LC_MONETARY category which should be used,
+   too.  Some of the information contradicts the information which can
+   be specified in format string.  */
+ssize_t
+__vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
+	      va_list ap)
+{
+  struct locale_data *current = loc->__locales[LC_MONETARY];
+#ifdef USE_IN_LIBIO
+  _IO_strfile f;
+# ifdef _IO_MTSAFE_IO
+  _IO_lock_t lock;
+# endif
+#else
+  FILE f;
+#endif
+  struct printf_info info;
+  char *dest;			/* Pointer so copy the output.  */
+  const char *fmt;		/* Pointer that walks through format.  */
+
+  dest = s;
+  fmt = format;
+
+  /* Loop through the format-string.  */
+  while (*fmt != '\0')
+    {
+      /* The floating-point value to output.  */
+      union
+      {
+	double dbl;
+	__long_double_t ldbl;
+      }
+      fpnum;
+      int int_format;
+      int print_curr_symbol;
+      int left_prec;
+      int left_pad;
+      int right_prec;
+      int group;
+      char pad;
+      int is_long_double;
+      int p_sign_posn;
+      int n_sign_posn;
+      int sign_posn;
+      int other_sign_posn;
+      int left;
+      int is_negative;
+      int sep_by_space;
+      int other_sep_by_space;
+      int cs_precedes;
+      int other_cs_precedes;
+      const char *sign_string;
+      const char *other_sign_string;
+      int done;
+      const char *currency_symbol;
+      size_t currency_symbol_len;
+      int width;
+      char *startp;
+      const void *ptr;
+      char space_char;
+
+      /* Process all character which do not introduce a format
+	 specification.  */
+      if (*fmt != '%')
+	{
+	  out_char (*fmt++);
+	  continue;
+	}
+
+      /* "%%" means a single '%' character.  */
+      if (fmt[1] == '%')
+	{
+	  out_char (*++fmt);
+	  ++fmt;
+	  continue;
+	}
+
+      /* Defaults for formatting.  */
+      int_format = 0;			/* Use international curr. symbol */
+      print_curr_symbol = 1;		/* Print the currency symbol.  */
+      left_prec = -1;			/* No left precision specified.  */
+      right_prec = -1;			/* No right precision specified.  */
+      group = 1;			/* Print digits grouped.  */
+      pad = ' ';			/* Fill character is <SP>.  */
+      is_long_double = 0;		/* Double argument by default.  */
+      p_sign_posn = -1;			/* This indicates whether the */
+      n_sign_posn = -1;			/* '(' flag is given.  */
+      width = -1;			/* No width specified so far.  */
+      left = 0;				/* Right justified by default.  */
+
+      /* Parse group characters.  */
+      while (1)
+	{
+	  switch (*++fmt)
+	    {
+	    case '=':			/* Set fill character.  */
+	      pad = *++fmt;
+	      if (pad == '\0')
+		{
+		  /* Premature EOS.  */
+		  __set_errno (EINVAL);
+		  return -1;
+		}
+	      continue;
+	    case '^':			/* Don't group digits.  */
+	      group = 0;
+	      continue;
+	    case '+':			/* Use +/- for sign of number.  */
+	      if (n_sign_posn != -1)
+		{
+		  __set_errno (EINVAL);
+		  return -1;
+		}
+	      p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN);
+	      n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN);
+	      continue;
+	    case '(':			/* Use ( ) for negative sign.  */
+	      if (n_sign_posn != -1)
+		{
+		  __set_errno (EINVAL);
+		  return -1;
+		}
+	      p_sign_posn = 0;
+	      n_sign_posn = 0;
+	      continue;
+	    case '!':			/* Don't print the currency symbol.  */
+	      print_curr_symbol = 0;
+	      continue;
+	    case '-':			/* Print left justified.  */
+	      left = 1;
+	      continue;
+	    default:
+	      /* Will stop the loop.  */;
+	    }
+	  break;
+	}
+
+      if (isdigit (*fmt))
+	{
+	  /* Parse field width.  */
+	  width = to_digit (*fmt);
+
+	  while (isdigit (*++fmt))
+	    {
+	      width *= 10;
+	      width += to_digit (*fmt);
+	    }
+
+	  /* If we don't have enough room for the demanded width we
+	     can stop now and return an error.  */
+	  if (dest + width >= s + maxsize)
+	    {
+	      __set_errno (E2BIG);
+	      return -1;
+	    }
+	}
+
+      /* Recognize left precision.  */
+      if (*fmt == '#')
+	{
+	  if (!isdigit (*++fmt))
+	    {
+	      __set_errno (EINVAL);
+	      return -1;
+	    }
+	  left_prec = to_digit (*fmt);
+
+	  while (isdigit (*++fmt))
+	    {
+	      left_prec *= 10;
+	      left_prec += to_digit (*fmt);
+	    }
+	}
+
+      /* Recognize right precision.  */
+      if (*fmt == '.')
+	{
+	  if (!isdigit (*++fmt))
+	    {
+	      __set_errno (EINVAL);
+	      return -1;
+	    }
+	  right_prec = to_digit (*fmt);
+
+	  while (isdigit (*++fmt))
+	    {
+	      right_prec *= 10;
+	      right_prec += to_digit (*fmt);
+	    }
+	}
+
+      /* Handle modifier.  This is an extension.  */
+      if (*fmt == 'L')
+	{
+	  ++fmt;
+	  is_long_double = 1;
+	}
+
+      /* Handle format specifier.  */
+      char int_symbol[4];
+      switch (*fmt++)
+	{
+	case 'i': {		/* Use international currency symbol.  */
+	  const char *int_curr_symbol;
+
+	  int_curr_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
+	  strncpy(int_symbol, int_curr_symbol, 3);
+	  int_symbol[3] = '\0';
+
+	  currency_symbol_len = 3;
+	  currency_symbol = &int_symbol[0];
+	  space_char = int_curr_symbol[3];
+	  int_format = 1;
+	  break;
+	}
+	case 'n':		/* Use national currency symbol.  */
+	  currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL);
+	  currency_symbol_len = strlen (currency_symbol);
+	  space_char = ' ';
+	  int_format = 0;
+	  break;
+	default:		/* Any unrecognized format is an error.  */
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+
+      /* If not specified by the format string now find the values for
+	 the format specification.  */
+      if (p_sign_posn == -1)
+	p_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SIGN_POSN : P_SIGN_POSN);
+      if (n_sign_posn == -1)
+	n_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SIGN_POSN : N_SIGN_POSN);
+
+      if (right_prec == -1)
+	{
+	  right_prec = *_NL_CURRENT (LC_MONETARY, int_format ? INT_FRAC_DIGITS : FRAC_DIGITS);
+
+	  if (right_prec == CHAR_MAX)
+	    right_prec = 2;
+	}
+
+      /* If we have to print the digits grouped determine how many
+	 extra characters this means.  */
+      if (group && left_prec != -1)
+	left_prec += __guess_grouping (left_prec,
+				       _NL_CURRENT (LC_MONETARY, MON_GROUPING),
+				       *_NL_CURRENT (LC_MONETARY,
+						     MON_THOUSANDS_SEP));
+
+      /* Now it's time to get the value.  */
+      if (is_long_double == 1)
+	{
+	  fpnum.ldbl = va_arg (ap, long double);
+	  is_negative = fpnum.ldbl < 0;
+	  if (is_negative)
+	    fpnum.ldbl = -fpnum.ldbl;
+	}
+      else
+	{
+	  fpnum.dbl = va_arg (ap, double);
+	  is_negative = fpnum.dbl < 0;
+	  if (is_negative)
+	    fpnum.dbl = -fpnum.dbl;
+	}
+
+      /* We now know the sign of the value and can determine the format.  */
+      if (is_negative)
+	{
+	  sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
+	  /* If the locale does not specify a character for the
+	     negative sign we use a '-'.  */
+	  if (*sign_string == '\0')
+	    sign_string = (const char *) "-";
+	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
+	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
+	  sign_posn = n_sign_posn;
+
+	  other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
+	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
+	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
+	  other_sign_posn = p_sign_posn;
+	}
+      else
+	{
+	  sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
+	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
+	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
+	  sign_posn = p_sign_posn;
+
+	  other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
+	  if (*other_sign_string == '\0')
+	    other_sign_string = (const char *) "-";
+	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
+	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
+	  other_sign_posn = n_sign_posn;
+	}
+
+      /* Set default values for unspecified information.  */
+      if (cs_precedes != 0)
+	cs_precedes = 1;
+      if (other_cs_precedes != 0)
+	other_cs_precedes = 1;
+      if (sep_by_space == CHAR_MAX)
+	sep_by_space = 0;
+      if (other_sep_by_space == CHAR_MAX)
+	other_sep_by_space = 0;
+      if (sign_posn == CHAR_MAX)
+	sign_posn = 1;
+      if (other_sign_posn == CHAR_MAX)
+	other_sign_posn = 1;
+
+      /* Check for degenerate cases */
+      if (sep_by_space == 2)
+	{
+	  if (sign_posn == 0 ||
+	      (sign_posn == 1 && !cs_precedes) ||
+	      (sign_posn == 2 && cs_precedes))
+	    /* sign and symbol are not adjacent, so no separator */
+	    sep_by_space = 0;
+	}
+      if (other_sep_by_space == 2)
+	{
+	  if (other_sign_posn == 0 ||
+	      (other_sign_posn == 1 && !other_cs_precedes) ||
+	      (other_sign_posn == 2 && other_cs_precedes))
+	    /* sign and symbol are not adjacent, so no separator */
+	    other_sep_by_space = 0;
+	}
+
+      /* Set the left precision and padding needed for alignment */
+      if (left_prec == -1)
+	{
+	  left_prec = 0;
+	  left_pad = 0;
+	}
+      else
+	{
+	  /* Set left_pad to number of spaces needed to align positive
+	     and negative formats */
+
+	  int left_bytes = 0;
+	  int other_left_bytes = 0;
+
+	  /* Work out number of bytes for currency string and separator
+	     preceding the value */
+	  if (cs_precedes)
+	    {
+	      left_bytes += currency_symbol_len;
+	      if (sep_by_space != 0)
+		++left_bytes;
+	    }
+
+	  if (other_cs_precedes)
+	    {
+	      other_left_bytes += currency_symbol_len;
+	      if (other_sep_by_space != 0)
+		++other_left_bytes;
+	    }
+
+	  /* Work out number of bytes for the sign (or left parenthesis)
+	     preceding the value */
+	  if (sign_posn == 0 && is_negative)
+	    ++left_bytes;
+	  else if (sign_posn == 1)
+	    left_bytes += strlen (sign_string);
+	  else if (cs_precedes && (sign_posn == 3 || sign_posn == 4))
+	    left_bytes += strlen (sign_string);
+
+	  if (other_sign_posn == 0 && !is_negative)
+	    ++other_left_bytes;
+	  else if (other_sign_posn == 1)
+	    other_left_bytes += strlen (other_sign_string);
+	  else if (other_cs_precedes &&
+		   (other_sign_posn == 3 || other_sign_posn == 4))
+	    other_left_bytes += strlen (other_sign_string);
+
+	  /* Compare the number of bytes preceding the value for
+	     each format, and set the padding accordingly */
+	  if (other_left_bytes > left_bytes)
+	    left_pad = other_left_bytes - left_bytes;
+	  else
+	    left_pad = 0;
+	}
+
+      /* Perhaps we'll someday make these things configurable so
+	 better start using symbolic names now.  */
+#define left_paren '('
+#define right_paren ')'
+
+      startp = dest;		/* Remember start so we can compute length.  */
+
+      while (left_pad-- > 0)
+	out_char (' ');
+
+      if (sign_posn == 0 && is_negative)
+	out_char (left_paren);
+
+      if (cs_precedes)
+	{
+	  if (sign_posn != 0 && sign_posn != 2 && sign_posn != 4
+	      && sign_posn != 5)
+	    {
+	      out_string (sign_string);
+	      if (sep_by_space == 2)
+		out_char (' ');
+	    }
+
+	  if (print_curr_symbol)
+	    {
+	      out_string (currency_symbol);
+
+	      if (sign_posn == 4)
+		{
+		  if (sep_by_space == 2)
+		    out_char (space_char);
+		  out_string (sign_string);
+		  if (sep_by_space == 1)
+		    /* POSIX.2 and SUS are not clear on this case, but C99
+		       says a space follows the adjacent-symbol-and-sign */
+		    out_char (' ');
+		}
+	      else
+		if (sep_by_space == 1)
+		  out_char (space_char);
+	    }
+	}
+      else
+	if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3
+	    && sign_posn != 4 && sign_posn != 5)
+	  out_string (sign_string);
+
+      /* Print the number.  */
+#ifdef USE_IN_LIBIO
+# ifdef _IO_MTSAFE_IO
+      f._sbf._f._lock = &lock;
+# endif
+      INTUSE(_IO_init) ((_IO_FILE *) &f, 0);
+      _IO_JUMPS ((struct _IO_FILE_plus *) &f) = &_IO_str_jumps;
+      INTUSE(_IO_str_init_static) ((_IO_strfile *) &f, dest,
+				   (s + maxsize) - dest, dest);
+#else
+      memset ((void *) &f, 0, sizeof (f));
+      f.__magic = _IOMAGIC;
+      f.__mode.__write = 1;
+      /* The buffer size is one less than MAXLEN
+	 so we have space for the null terminator.  */
+      f.__bufp = f.__buffer = (char *) dest;
+      f.__bufsize = (s + maxsize) - dest;
+      f.__put_limit = f.__buffer + f.__bufsize;
+      f.__get_limit = f.__buffer;
+      /* After the buffer is full (MAXLEN characters have been written),
+	 any more characters written will go to the bit bucket.  */
+      f.__room_funcs = __default_room_functions;
+      f.__io_funcs.__write = NULL;
+      f.__seen = 1;
+#endif
+      /* We clear the last available byte so we can find out whether
+	 the numeric representation is too long.  */
+      s[maxsize - 1] = '\0';
+
+      info.prec = right_prec;
+      info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
+      info.spec = 'f';
+      info.is_long_double = is_long_double;
+      info.is_short = 0;
+      info.is_long = 0;
+      info.alt = 0;
+      info.space = 0;
+      info.left = 0;
+      info.showsign = 0;
+      info.group = group;
+      info.pad = pad;
+      info.extra = 1;		/* This means use values from LC_MONETARY.  */
+      info.wide = 0;
+
+      ptr = &fpnum;
+      done = __printf_fp ((FILE *) &f, &info, &ptr);
+      if (done < 0)
+	return -1;
+
+      if (s[maxsize - 1] != '\0')
+	{
+	  __set_errno (E2BIG);
+	  return -1;
+	}
+
+      dest += done;
+
+      if (!cs_precedes)
+	{
+	  if (sign_posn == 3)
+	    {
+	      if (sep_by_space == 1)
+		out_char (' ');
+	      out_string (sign_string);
+	    }
+
+	  if (print_curr_symbol)
+	    {
+	      if ((sign_posn == 3 && sep_by_space == 2)
+		  || (sign_posn == 4 && sep_by_space == 1)
+		  || (sign_posn == 2 && sep_by_space == 1)
+		  || (sign_posn == 1 && sep_by_space == 1)
+		  || (sign_posn == 0 && sep_by_space == 1))
+		out_char (space_char);
+	      out_nstring (currency_symbol, currency_symbol_len);
+	      if (sign_posn == 4)
+		{
+		  if (sep_by_space == 2)
+		    out_char (' ');
+		  out_string (sign_string);
+		}
+	    }
+	}
+
+      if (sign_posn == 2)
+	{
+	  if (sep_by_space == 2)
+	    out_char (' ');
+	  out_string (sign_string);
+	}
+
+      if (sign_posn == 0 && is_negative)
+	out_char (right_paren);
+
+      /* Now test whether the output width is filled.  */
+      if (dest - startp < width)
+	{
+	  if (left)
+	    /* We simply have to fill using spaces.  */
+	    do
+	      out_char (' ');
+	    while (dest - startp < width);
+	  else
+	    {
+	      int dist = width - (dest - startp);
+	      char *cp;
+	      for (cp = dest - 1; cp >= startp; --cp)
+		cp[dist] = cp[0];
+
+	      dest += dist;
+
+	      do
+		startp[--dist] = ' ';
+	      while (dist > 0);
+	    }
+	}
+    }
+
+  /* Terminate the string.  */
+  *dest = '\0';
+
+  return dest - s;
+}
+
+ssize_t
+__strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...)
+{
+  va_list ap;
+
+  va_start (ap, format);
+
+  ssize_t res = __vstrfmon_l (s, maxsize, loc, format, ap);
+
+  va_end (ap);
+
+  return res;
+}
 weak_alias (__strfmon_l, strfmon_l)
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 63d7a4d5bb..1d4e4a4c29 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -1,6 +1,6 @@
 /* Read decimal floating point numbers.
    This file is part of the GNU C Library.
-   Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -18,1579 +18,53 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* Configuration part.  These macros are defined by `strtold.c',
-   `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the
-   `long double' and `float' versions of the reader.  */
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale/localeinfo.h>
+
+
 #ifndef FLOAT
-# define FLOAT		double
-# define FLT		DBL
+# define FLOAT double
 # ifdef USE_WIDE_CHAR
-#  ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#   define STRTOF	__wcstod_l
-#  else
-#   define STRTOF	wcstod
-#  endif
+#  define STRTOF wcstod
+#  define STRTOF_L __wcstod_l
 # else
-#  ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#   define STRTOF	__strtod_l
-#  else
-#   define STRTOF	strtod
-#  endif
+#  define STRTOF strtod
+#  define STRTOF_L __strtod_l
 # endif
-# define MPN2FLOAT	__mpn_construct_double
-# define FLOAT_HUGE_VAL	HUGE_VAL
-# define SET_MANTISSA(flt, mant) \
-  do { union ieee754_double u;						      \
-       u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
-  } while (0)
-#endif
-/* End of configuration part.  */
-
-#include <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <ieee754.h>
-#include "../locale/localeinfo.h"
-#include <locale.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* The gmp headers need some configuration frobs.  */
-#define HAVE_ALLOCA 1
-
-/* Include gmp-mparam.h first, such that definitions of _SHORT_LIMB
-   and _LONG_LONG_LIMB in it can take effect into gmp.h.  */
-#include <gmp-mparam.h>
-#include <gmp.h>
-#include <gmp-impl.h>
-#include <longlong.h>
-#include "fpioconst.h"
-
-#define NDEBUG 1
-#include <assert.h>
-
-
-/* We use this code also for the extended locale handling where the
-   function gets as an additional argument the locale which has to be
-   used.  To access the values we have to redefine the _NL_CURRENT
-   macro.  */
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# undef _NL_CURRENT
-# define _NL_CURRENT(category, item) \
-  (current->values[_NL_ITEM_INDEX (item)].string)
-# define LOCALE_PARAM , loc
-# define LOCALE_PARAM_DECL __locale_t loc;
-#else
-# define LOCALE_PARAM
-# define LOCALE_PARAM_DECL
-#endif
-
-#if defined _LIBC || defined HAVE_WCHAR_H
-# include <wchar.h>
 #endif
 
 #ifdef USE_WIDE_CHAR
 # include <wctype.h>
 # define STRING_TYPE wchar_t
-# define CHAR_TYPE wint_t
-# define L_(Ch) L##Ch
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
-#  define ISDIGIT(Ch) __iswdigit_l ((Ch), loc)
-#  define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc)
-#  define TOLOWER(Ch) __towlower_l ((Ch), loc)
-#  define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc)
-#  define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
-# else
-#  define ISSPACE(Ch) iswspace (Ch)
-#  define ISDIGIT(Ch) iswdigit (Ch)
-#  define ISXDIGIT(Ch) iswxdigit (Ch)
-#  define TOLOWER(Ch) towlower (Ch)
-#  define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N))
-#  define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0)
-# endif
 #else
 # define STRING_TYPE char
-# define CHAR_TYPE char
-# define L_(Ch) Ch
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#  define ISSPACE(Ch) __isspace_l ((Ch), loc)
-#  define ISDIGIT(Ch) __isdigit_l ((Ch), loc)
-#  define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc)
-#  define TOLOWER(Ch) __tolower_l ((Ch), loc)
-#  define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc)
-#  define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
-# else
-#  define ISSPACE(Ch) isspace (Ch)
-#  define ISDIGIT(Ch) isdigit (Ch)
-#  define ISXDIGIT(Ch) isxdigit (Ch)
-#  define TOLOWER(Ch) tolower (Ch)
-#  define STRNCASECMP(S1, S2, N) __strncasecmp ((S1), (S2), (N))
-#  define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B))
-# endif
-#endif
-
-
-/* Constants we need from float.h; select the set for the FLOAT precision.  */
-#define MANT_DIG	PASTE(FLT,_MANT_DIG)
-#define	DIG		PASTE(FLT,_DIG)
-#define	MAX_EXP		PASTE(FLT,_MAX_EXP)
-#define	MIN_EXP		PASTE(FLT,_MIN_EXP)
-#define MAX_10_EXP	PASTE(FLT,_MAX_10_EXP)
-#define MIN_10_EXP	PASTE(FLT,_MIN_10_EXP)
-
-/* Extra macros required to get FLT expanded before the pasting.  */
-#define PASTE(a,b)	PASTE1(a,b)
-#define PASTE1(a,b)	a##b
-
-/* Function to construct a floating point number from an MP integer
-   containing the fraction bits, a base 2 exponent, and a sign flag.  */
-extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
-
-/* Definitions according to limb size used.  */
-#if	BITS_PER_MP_LIMB == 32
-#  define MAX_DIG_PER_LIMB	9
-#  define MAX_FAC_PER_LIMB	1000000000UL
-#elif	BITS_PER_MP_LIMB == 64
-#  define MAX_DIG_PER_LIMB	19
-#  define MAX_FAC_PER_LIMB	10000000000000000000ULL
-#else
-#  error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
 #endif
 
-
-/* Local data structure.  */
-static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
-{    0,                   10,                   100,
-     1000,                10000,                100000L,
-     1000000L,            10000000L,            100000000L,
-     1000000000L
-#if BITS_PER_MP_LIMB > 32
-	        ,	  10000000000ULL,       100000000000ULL,
-     1000000000000ULL,    10000000000000ULL,    100000000000000ULL,
-     1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
-     1000000000000000000ULL, 10000000000000000000ULL
-#endif
-#if BITS_PER_MP_LIMB > 64
-  #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
-#endif
-};
-
-#ifndef	howmany
-#define	howmany(x,y)		(((x)+((y)-1))/(y))
-#endif
-#define SWAP(x, y)		({ typeof(x) _tmp = x; x = y; y = _tmp; })
-
-#define NDIG			(MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG)
-#define HEXNDIG			((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG)
-#define	RETURN_LIMB_SIZE		howmany (MANT_DIG, BITS_PER_MP_LIMB)
-
-#define RETURN(val,end)							      \
-    do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end);		      \
-	 return val; } while (0)
-
-/* Maximum size necessary for mpn integers to hold floating point numbers.  */
-#define	MPNSIZE		(howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \
-			 + 2)
-/* Declare an mpn integer variable that big.  */
-#define	MPN_VAR(name)	mp_limb_t name[MPNSIZE]; mp_size_t name##size
-/* Copy an mpn integer value.  */
-#define MPN_ASSIGN(dst, src) \
-	memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t))
-
-
-/* Return a floating point number of the needed type according to the given
-   multi-precision number after possible rounding.  */
-static FLOAT
-round_and_return (mp_limb_t *retval, int exponent, int negative,
-		  mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
-{
-  if (exponent < MIN_EXP - 1)
-    {
-      mp_size_t shift = MIN_EXP - 1 - exponent;
-
-      if (shift > MANT_DIG)
-	{
-	  __set_errno (EDOM);
-	  return 0.0;
-	}
-
-      more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
-      if (shift == MANT_DIG)
-	/* This is a special case to handle the very seldom case where
-	   the mantissa will be empty after the shift.  */
-	{
-	  int i;
-
-	  round_limb = retval[RETURN_LIMB_SIZE - 1];
-	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
-	    more_bits |= retval[i] != 0;
-	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
-	}
-      else if (shift >= BITS_PER_MP_LIMB)
-	{
-	  int i;
-
-	  round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
-	  round_bit = (shift - 1) % BITS_PER_MP_LIMB;
-	  for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i)
-	    more_bits |= retval[i] != 0;
-	  more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1))
-			!= 0);
-
-	  (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
-                               RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
-                               shift % BITS_PER_MP_LIMB);
-          MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
-                    shift / BITS_PER_MP_LIMB);
-	}
-      else if (shift > 0)
-	{
-          round_limb = retval[0];
-          round_bit = shift - 1;
-	  (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
-	}
-      /* This is a hook for the m68k long double format, where the
-	 exponent bias is the same for normalized and denormalized
-	 numbers.  */
-#ifndef DENORM_EXP
-# define DENORM_EXP (MIN_EXP - 2)
-#endif
-      exponent = DENORM_EXP;
-    }
-
-  if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
-      && (more_bits || (retval[0] & 1) != 0
-          || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
-    {
-      mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
-
-      if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) ||
-          ((MANT_DIG % BITS_PER_MP_LIMB) != 0 &&
-           (retval[RETURN_LIMB_SIZE - 1]
-            & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0))
-	{
-	  ++exponent;
-	  (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1);
-	  retval[RETURN_LIMB_SIZE - 1]
-	    |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB);
-	}
-      else if (exponent == DENORM_EXP
-	       && (retval[RETURN_LIMB_SIZE - 1]
-		   & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB)))
-	       != 0)
-	  /* The number was denormalized but now normalized.  */
-	exponent = MIN_EXP - 1;
-    }
-
-  if (exponent > MAX_EXP)
-    return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
-
-  return MPN2FLOAT (retval, exponent, negative);
-}
-
-
-/* Read a multi-precision integer starting at STR with exactly DIGCNT digits
-   into N.  Return the size of the number limbs in NSIZE at the first
-   character od the string that is not part of the integer as the function
-   value.  If the EXPONENT is small enough to be taken as an additional
-   factor for the resulting number (see code) multiply by it.  */
-static const STRING_TYPE *
-str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
-	    int *exponent
-#ifndef USE_WIDE_CHAR
-	    , const char *decimal, size_t decimal_len, const char *thousands
-#endif
-
-	    )
-{
-  /* Number of digits for actual limb.  */
-  int cnt = 0;
-  mp_limb_t low = 0;
-  mp_limb_t start;
-
-  *nsize = 0;
-  assert (digcnt > 0);
-  do
-    {
-      if (cnt == MAX_DIG_PER_LIMB)
-	{
-	  if (*nsize == 0)
-	    {
-	      n[0] = low;
-	      *nsize = 1;
-	    }
-	  else
-	    {
-	      mp_limb_t cy;
-	      cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB);
-	      cy += __mpn_add_1 (n, n, *nsize, low);
-	      if (cy != 0)
-		{
-		  n[*nsize] = cy;
-		  ++(*nsize);
-		}
-	    }
-	  cnt = 0;
-	  low = 0;
-	}
-
-      /* There might be thousands separators or radix characters in
-	 the string.  But these all can be ignored because we know the
-	 format of the number is correct and we have an exact number
-	 of characters to read.  */
-#ifdef USE_WIDE_CHAR
-      if (*str < L'0' || *str > L'9')
-	++str;
-#else
-      if (*str < '0' || *str > '9')
-	{
-	  int inner = 0;
-	  if (thousands != NULL && *str == *thousands
-	      && ({ for (inner = 1; thousands[inner] != '\0'; ++inner)
-		      if (thousands[inner] != str[inner])
-			break;
-		    thousands[inner] == '\0'; }))
-	    str += inner;
-	  else
-	    str += decimal_len;
-	}
-#endif
-      low = low * 10 + *str++ - L_('0');
-      ++cnt;
-    }
-  while (--digcnt > 0);
-
-  if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
-    {
-      low *= _tens_in_limb[*exponent];
-      start = _tens_in_limb[cnt + *exponent];
-      *exponent = 0;
-    }
-  else
-    start = _tens_in_limb[cnt];
-
-  if (*nsize == 0)
-    {
-      n[0] = low;
-      *nsize = 1;
-    }
-  else
-    {
-      mp_limb_t cy;
-      cy = __mpn_mul_1 (n, n, *nsize, start);
-      cy += __mpn_add_1 (n, n, *nsize, low);
-      if (cy != 0)
-	n[(*nsize)++] = cy;
-    }
-
-  return str;
-}
-
-
-/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits
-   with the COUNT most significant bits of LIMB.
-
-   Tege doesn't like this function so I have to write it here myself. :)
-   --drepper */
-static inline void
-__attribute ((always_inline))
-__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
-		mp_limb_t limb)
-{
-  if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB)
-    {
-      /* Optimize the case of shifting by exactly a word:
-	 just copy words, with no actual bit-shifting.  */
-      mp_size_t i;
-      for (i = size - 1; i > 0; --i)
-	ptr[i] = ptr[i - 1];
-      ptr[0] = limb;
-    }
-  else
-    {
-      (void) __mpn_lshift (ptr, ptr, size, count);
-      ptr[0] |= limb >> (BITS_PER_MP_LIMB - count);
-    }
-}
-
-
 #define INTERNAL(x) INTERNAL1(x)
 #define INTERNAL1(x) __##x##_internal
 
-/* This file defines a function to check for correct grouping.  */
-#include "grouping.h"
 
-
-/* Return a floating point number with the value of the given string NPTR.
-   Set *ENDPTR to the character after the last used one.  If the number is
-   smaller than the smallest representable number, set `errno' to ERANGE and
-   return 0.0.  If the number is too big to be represented, set `errno' to
-   ERANGE and return HUGE_VAL with the appropriate sign.  */
 FLOAT
-INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
+INTERNAL (STRTOF) (nptr, endptr, group)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
      int group;
-     LOCALE_PARAM_DECL
 {
-  int negative;			/* The sign of the number.  */
-  MPN_VAR (num);		/* MP representation of the number.  */
-  int exponent;			/* Exponent of the number.  */
-
-  /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
-  int base = 10;
-
-  /* When we have to compute fractional digits we form a fraction with a
-     second multi-precision number (and we sometimes need a second for
-     temporary results).  */
-  MPN_VAR (den);
-
-  /* Representation for the return value.  */
-  mp_limb_t retval[RETURN_LIMB_SIZE];
-  /* Number of bits currently in result value.  */
-  int bits;
-
-  /* Running pointer after the last character processed in the string.  */
-  const STRING_TYPE *cp, *tp;
-  /* Start of significant part of the number.  */
-  const STRING_TYPE *startp, *start_of_digits;
-  /* Points at the character following the integer and fractional digits.  */
-  const STRING_TYPE *expp;
-  /* Total number of digit and number of digits in integer part.  */
-  int dig_no, int_no, lead_zero;
-  /* Contains the last character read.  */
-  CHAR_TYPE c;
-
-/* We should get wint_t from <stddef.h>, but not all GCC versions define it
-   there.  So define it ourselves if it remains undefined.  */
-#ifndef _WINT_T
-  typedef unsigned int wint_t;
-#endif
-  /* The radix character of the current locale.  */
-#ifdef USE_WIDE_CHAR
-  wchar_t decimal;
-#else
-  const char *decimal;
-  size_t decimal_len;
-#endif
-  /* The thousands character of the current locale.  */
-#ifdef USE_WIDE_CHAR
-  wchar_t thousands = L'\0';
-#else
-  const char *thousands = NULL;
-#endif
-  /* The numeric grouping specification of the current locale,
-     in the format described in <locale.h>.  */
-  const char *grouping;
-  /* Used in several places.  */
-  int cnt;
-
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-  struct locale_data *current = loc->__locales[LC_NUMERIC];
-#endif
-
-  if (group)
-    {
-      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-      if (*grouping <= 0 || *grouping == CHAR_MAX)
-	grouping = NULL;
-      else
-	{
-	  /* Figure out the thousands separator character.  */
-#ifdef USE_WIDE_CHAR
-	  thousands = _NL_CURRENT_WORD (LC_NUMERIC,
-					_NL_NUMERIC_THOUSANDS_SEP_WC);
-	  if (thousands == L'\0')
-	    grouping = NULL;
-#else
-	  thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
-	  if (*thousands == '\0')
-	    {
-	      thousands = NULL;
-	      grouping = NULL;
-	    }
-#endif
-	}
-    }
-  else
-    grouping = NULL;
-
-  /* Find the locale's decimal point character.  */
-#ifdef USE_WIDE_CHAR
-  decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
-  assert (decimal != L'\0');
-# define decimal_len 1
-#else
-  decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
-  decimal_len = strlen (decimal);
-  assert (decimal_len > 0);
-#endif
-
-  /* Prepare number representation.  */
-  exponent = 0;
-  negative = 0;
-  bits = 0;
-
-  /* Parse string to get maximal legal prefix.  We need the number of
-     characters of the integer part, the fractional part and the exponent.  */
-  cp = nptr - 1;
-  /* Ignore leading white space.  */
-  do
-    c = *++cp;
-  while (ISSPACE (c));
-
-  /* Get sign of the result.  */
-  if (c == L_('-'))
-    {
-      negative = 1;
-      c = *++cp;
-    }
-  else if (c == L_('+'))
-    c = *++cp;
-
-  /* Return 0.0 if no legal string is found.
-     No character is used even if a sign was found.  */
-#ifdef USE_WIDE_CHAR
-  if (c == (wint_t) decimal
-      && (wint_t) cp[1] >= L'0' && (wint_t) cp[1] <= L'9')
-    {
-      /* We accept it.  This funny construct is here only to indent
-	 the code directly.  */
-    }
-#else
-  for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
-    if (cp[cnt] != decimal[cnt])
-      break;
-  if (decimal[cnt] == '\0' && cp[cnt] >= '0' && cp[cnt] <= '9')
-    {
-      /* We accept it.  This funny construct is here only to indent
-	 the code directly.  */
-    }
-#endif
-  else if (c < L_('0') || c > L_('9'))
-    {
-      /* Check for `INF' or `INFINITY'.  */
-      if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
-	{
-	  /* Return +/- infinity.  */
-	  if (endptr != NULL)
-	    *endptr = (STRING_TYPE *)
-		      (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0
-			     ? 8 : 3));
-
-	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
-	}
-
-      if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
-	{
-	  /* Return NaN.  */
-	  FLOAT retval = NAN;
-
-	  cp += 3;
-
-	  /* Match `(n-char-sequence-digit)'.  */
-	  if (*cp == L_('('))
-	    {
-	      const STRING_TYPE *startp = cp;
-	      do
-		++cp;
-	      while ((*cp >= L_('0') && *cp <= L_('9'))
-		     || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z'))
-		     || *cp == L_('_'));
-
-	      if (*cp != L_(')'))
-		/* The closing brace is missing.  Only match the NAN
-		   part.  */
-		cp = startp;
-	      else
-		{
-		  /* This is a system-dependent way to specify the
-		     bitmask used for the NaN.  We expect it to be
-		     a number which is put in the mantissa of the
-		     number.  */
-		  STRING_TYPE *endp;
-		  unsigned long long int mant;
-
-		  mant = STRTOULL (startp + 1, &endp, 0);
-		  if (endp == cp)
-		    SET_MANTISSA (retval, mant);
-		}
-	    }
-
-	  if (endptr != NULL)
-	    *endptr = (STRING_TYPE *) cp;
-
-	  return retval;
-	}
-
-      /* It is really a text we do not recognize.  */
-      RETURN (0.0, nptr);
-    }
-
-  /* First look whether we are faced with a hexadecimal number.  */
-  if (c == L_('0') && TOLOWER (cp[1]) == L_('x'))
-    {
-      /* Okay, it is a hexa-decimal number.  Remember this and skip
-	 the characters.  BTW: hexadecimal numbers must not be
-	 grouped.  */
-      base = 16;
-      cp += 2;
-      c = *cp;
-      grouping = NULL;
-    }
-
-  /* Record the start of the digits, in case we will check their grouping.  */
-  start_of_digits = startp = cp;
-
-  /* Ignore leading zeroes.  This helps us to avoid useless computations.  */
-#ifdef USE_WIDE_CHAR
-  while (c == L'0' || ((wint_t) thousands != L'\0' && c == (wint_t) thousands))
-    c = *++cp;
-#else
-  if (thousands == NULL)
-    while (c == '0')
-      c = *++cp;
-  else
-    {
-      /* We also have the multibyte thousands string.  */
-      while (1)
-	{
-	  if (c != '0')
-	    {
-	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-		if (c != thousands[cnt])
-		  break;
-	      if (thousands[cnt] != '\0')
-		break;
-	    }
-	  c = *++cp;
-	}
-    }
-#endif
-
-  /* If no other digit but a '0' is found the result is 0.0.
-     Return current read pointer.  */
-  if ((c < L_('0') || c > L_('9'))
-      && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
-			 || c > (CHAR_TYPE) TOLOWER (L_('f'))))
-#ifdef USE_WIDE_CHAR
-      && c != (wint_t) decimal
-#else
-      && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
-	      if (decimal[cnt] != cp[cnt])
-		break;
-	    decimal[cnt] != '\0'; })
-#endif
-      && (base == 16 && (cp == start_of_digits
-			 || (CHAR_TYPE) TOLOWER (c) != L_('p')))
-      && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
-    {
-#ifdef USE_WIDE_CHAR
-      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
-					 grouping);
-#else
-      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
-					 grouping);
-#endif
-      /* If TP is at the start of the digits, there was no correctly
-	 grouped prefix of the string; so no number found.  */
-      RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
-    }
-
-  /* Remember first significant digit and read following characters until the
-     decimal point, exponent character or any non-FP number character.  */
-  startp = cp;
-  dig_no = 0;
-  while (1)
-    {
-      if ((c >= L_('0') && c <= L_('9'))
-	  || (base == 16 && (wint_t) TOLOWER (c) >= L_('a')
-	      && (wint_t) TOLOWER (c) <= L_('f')))
-	++dig_no;
-      else
-	{
-#ifdef USE_WIDE_CHAR
-	  if ((wint_t) thousands == L'\0' || c != (wint_t) thousands)
-	    /* Not a digit or separator: end of the integer part.  */
-	    break;
-#else
-	  if (thousands == NULL)
-	    break;
-	  else
-	    {
-	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-		if (thousands[cnt] != cp[cnt])
-		  break;
-	      if (thousands[cnt] != '\0')
-		break;
-	    }
-#endif
-	}
-      c = *++cp;
-    }
-
-  if (grouping && dig_no > 0)
-    {
-      /* Check the grouping of the digits.  */
-#ifdef USE_WIDE_CHAR
-      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
-					 grouping);
-#else
-      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
-					 grouping);
-#endif
-      if (cp != tp)
-        {
-	  /* Less than the entire string was correctly grouped.  */
-
-	  if (tp == start_of_digits)
-	    /* No valid group of numbers at all: no valid number.  */
-	    RETURN (0.0, nptr);
-
-	  if (tp < startp)
-	    /* The number is validly grouped, but consists
-	       only of zeroes.  The whole value is zero.  */
-	    RETURN (0.0, tp);
-
-	  /* Recompute DIG_NO so we won't read more digits than
-	     are properly grouped.  */
-	  cp = tp;
-	  dig_no = 0;
-	  for (tp = startp; tp < cp; ++tp)
-	    if (*tp >= L_('0') && *tp <= L_('9'))
-	      ++dig_no;
-
-	  int_no = dig_no;
-	  lead_zero = 0;
-
-	  goto number_parsed;
-	}
-    }
-
-  /* We have the number digits in the integer part.  Whether these are all or
-     any is really a fractional digit will be decided later.  */
-  int_no = dig_no;
-  lead_zero = int_no == 0 ? -1 : 0;
-
-  /* Read the fractional digits.  A special case are the 'american style'
-     numbers like `16.' i.e. with decimal but without trailing digits.  */
-  if (
-#ifdef USE_WIDE_CHAR
-      c == (wint_t) decimal
-#else
-      ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
-	   if (decimal[cnt] != cp[cnt])
-	     break;
-	 decimal[cnt] == '\0'; })
-#endif
-      )
-    {
-      cp += decimal_len;
-      c = *cp;
-      while ((c >= L_('0') && c <= L_('9')) ||
-	     (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
-	{
-	  if (c != L_('0') && lead_zero == -1)
-	    lead_zero = dig_no - int_no;
-	  ++dig_no;
-	  c = *++cp;
-	}
-    }
-
-  /* Remember start of exponent (if any).  */
-  expp = cp;
-
-  /* Read exponent.  */
-  if ((base == 16 && TOLOWER (c) == L_('p'))
-      || (base != 16 && TOLOWER (c) == L_('e')))
-    {
-      int exp_negative = 0;
-
-      c = *++cp;
-      if (c == L_('-'))
-	{
-	  exp_negative = 1;
-	  c = *++cp;
-	}
-      else if (c == L_('+'))
-	c = *++cp;
-
-      if (c >= L_('0') && c <= L_('9'))
-	{
-	  int exp_limit;
-
-	  /* Get the exponent limit. */
-	  if (base == 16)
-	    exp_limit = (exp_negative ?
-			 -MIN_EXP + MANT_DIG + 4 * int_no :
-			 MAX_EXP - 4 * int_no + lead_zero);
-	  else
-	    exp_limit = (exp_negative ?
-			 -MIN_10_EXP + MANT_DIG + int_no :
-			 MAX_10_EXP - int_no + lead_zero);
-
-	  do
-	    {
-	      exponent *= 10;
-
-	      if (exponent > exp_limit)
-		/* The exponent is too large/small to represent a valid
-		   number.  */
-		{
-	 	  FLOAT result;
-
-		  /* We have to take care for special situation: a joker
-		     might have written "0.0e100000" which is in fact
-		     zero.  */
-		  if (lead_zero == -1)
-		    result = negative ? -0.0 : 0.0;
-		  else
-		    {
-		      /* Overflow or underflow.  */
-		      __set_errno (ERANGE);
-		      result = (exp_negative ? 0.0 :
-				negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
-		    }
-
-		  /* Accept all following digits as part of the exponent.  */
-		  do
-		    ++cp;
-		  while (*cp >= L_('0') && *cp <= L_('9'));
-
-		  RETURN (result, cp);
-		  /* NOTREACHED */
-		}
-
-	      exponent += c - L_('0');
-	      c = *++cp;
-	    }
-	  while (c >= L_('0') && c <= L_('9'));
-
-	  if (exp_negative)
-	    exponent = -exponent;
-	}
-      else
-	cp = expp;
-    }
-
-  /* We don't want to have to work with trailing zeroes after the radix.  */
-  if (dig_no > int_no)
-    {
-      while (expp[-1] == L_('0'))
-	{
-	  --expp;
-	  --dig_no;
-	}
-      assert (dig_no >= int_no);
-    }
-
-  if (dig_no == int_no && dig_no > 0 && exponent < 0)
-    do
-      {
-	while (! (base == 16 ? ISXDIGIT (expp[-1]) : ISDIGIT (expp[-1])))
-	  --expp;
-
-	if (expp[-1] != L_('0'))
-	  break;
-
-	--expp;
-	--dig_no;
-	--int_no;
-	++exponent;
-      }
-    while (dig_no > 0 && exponent < 0);
-
- number_parsed:
-
-  /* The whole string is parsed.  Store the address of the next character.  */
-  if (endptr)
-    *endptr = (STRING_TYPE *) cp;
-
-  if (dig_no == 0)
-    return negative ? -0.0 : 0.0;
-
-  if (lead_zero)
-    {
-      /* Find the decimal point */
-#ifdef USE_WIDE_CHAR
-      while (*startp != decimal)
-	++startp;
-#else
-      while (1)
-	{
-	  if (*startp == decimal[0])
-	    {
-	      for (cnt = 1; decimal[cnt] != '\0'; ++cnt)
-		if (decimal[cnt] != startp[cnt])
-		  break;
-	      if (decimal[cnt] == '\0')
-		break;
-	    }
-	  ++startp;
-	}
-#endif
-      startp += lead_zero + decimal_len;
-      exponent -= base == 16 ? 4 * lead_zero : lead_zero;
-      dig_no -= lead_zero;
-    }
-
-  /* If the BASE is 16 we can use a simpler algorithm.  */
-  if (base == 16)
-    {
-      static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3,
-				     4, 4, 4, 4, 4, 4, 4, 4 };
-      int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB;
-      int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-      mp_limb_t val;
-
-      while (!ISXDIGIT (*startp))
-	++startp;
-      while (*startp == L_('0'))
-	++startp;
-      if (ISDIGIT (*startp))
-	val = *startp++ - L_('0');
-      else
-	val = 10 + TOLOWER (*startp++) - L_('a');
-      bits = nbits[val];
-      /* We cannot have a leading zero.  */
-      assert (bits != 0);
-
-      if (pos + 1 >= 4 || pos + 1 >= bits)
-	{
-	  /* We don't have to care for wrapping.  This is the normal
-	     case so we add the first clause in the `if' expression as
-	     an optimization.  It is a compile-time constant and so does
-	     not cost anything.  */
-	  retval[idx] = val << (pos - bits + 1);
-	  pos -= bits;
-	}
-      else
-	{
-	  retval[idx--] = val >> (bits - pos - 1);
-	  retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1));
-	  pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1);
-	}
-
-      /* Adjust the exponent for the bits we are shifting in.  */
-      exponent += bits - 1 + (int_no - 1) * 4;
-
-      while (--dig_no > 0 && idx >= 0)
-	{
-	  if (!ISXDIGIT (*startp))
-	    startp += decimal_len;
-	  if (ISDIGIT (*startp))
-	    val = *startp++ - L_('0');
-	  else
-	    val = 10 + TOLOWER (*startp++) - L_('a');
-
-	  if (pos + 1 >= 4)
-	    {
-	      retval[idx] |= val << (pos - 4 + 1);
-	      pos -= 4;
-	    }
-	  else
-	    {
-	      retval[idx--] |= val >> (4 - pos - 1);
-	      val <<= BITS_PER_MP_LIMB - (4 - pos - 1);
-	      if (idx < 0)
-		return round_and_return (retval, exponent, negative, val,
-					 BITS_PER_MP_LIMB - 1, dig_no > 0);
-
-	      retval[idx] = val;
-	      pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1);
-	    }
-	}
-
-      /* We ran out of digits.  */
-      MPN_ZERO (retval, idx);
-
-      return round_and_return (retval, exponent, negative, 0, 0, 0);
-    }
-
-  /* Now we have the number of digits in total and the integer digits as well
-     as the exponent and its sign.  We can decide whether the read digits are
-     really integer digits or belong to the fractional part; i.e. we normalize
-     123e-2 to 1.23.  */
-  {
-    register int incr = (exponent < 0 ? MAX (-int_no, exponent)
-			 : MIN (dig_no - int_no, exponent));
-    int_no += incr;
-    exponent -= incr;
-  }
-
-  if (int_no + exponent > MAX_10_EXP + 1)
-    {
-      __set_errno (ERANGE);
-      return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
-    }
-
-  if (exponent < MIN_10_EXP - (DIG + 1))
-    {
-      __set_errno (ERANGE);
-      return 0.0;
-    }
-
-  if (int_no > 0)
-    {
-      /* Read the integer part as a multi-precision number to NUM.  */
-      startp = str_to_mpn (startp, int_no, num, &numsize, &exponent
-#ifndef USE_WIDE_CHAR
-			   , decimal, decimal_len, thousands
-#endif
-			   );
-
-      if (exponent > 0)
-	{
-	  /* We now multiply the gained number by the given power of ten.  */
-	  mp_limb_t *psrc = num;
-	  mp_limb_t *pdest = den;
-	  int expbit = 1;
-	  const struct mp_power *ttab = &_fpioconst_pow10[0];
-
-	  do
-	    {
-	      if ((exponent & expbit) != 0)
-		{
-		  size_t size = ttab->arraysize - _FPIO_CONST_OFFSET;
-		  mp_limb_t cy;
-		  exponent ^= expbit;
-
-		  /* FIXME: not the whole multiplication has to be
-		     done.  If we have the needed number of bits we
-		     only need the information whether more non-zero
-		     bits follow.  */
-		  if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET)
-		    cy = __mpn_mul (pdest, psrc, numsize,
-				    &__tens[ttab->arrayoff
-					   + _FPIO_CONST_OFFSET],
-				    size);
-		  else
-		    cy = __mpn_mul (pdest, &__tens[ttab->arrayoff
-						  + _FPIO_CONST_OFFSET],
-				    size, psrc, numsize);
-		  numsize += size;
-		  if (cy == 0)
-		    --numsize;
-		  (void) SWAP (psrc, pdest);
-		}
-	      expbit <<= 1;
-	      ++ttab;
-	    }
-	  while (exponent != 0);
-
-	  if (psrc == den)
-	    memcpy (num, den, numsize * sizeof (mp_limb_t));
-	}
-
-      /* Determine how many bits of the result we already have.  */
-      count_leading_zeros (bits, num[numsize - 1]);
-      bits = numsize * BITS_PER_MP_LIMB - bits;
-
-      /* Now we know the exponent of the number in base two.
-	 Check it against the maximum possible exponent.  */
-      if (bits > MAX_EXP)
-	{
-	  __set_errno (ERANGE);
-	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
-	}
-
-      /* We have already the first BITS bits of the result.  Together with
-	 the information whether more non-zero bits follow this is enough
-	 to determine the result.  */
-      if (bits > MANT_DIG)
-	{
-	  int i;
-	  const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB;
-	  const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB;
-	  const mp_size_t round_idx = least_bit == 0 ? least_idx - 1
-						     : least_idx;
-	  const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1
-						     : least_bit - 1;
-
-	  if (least_bit == 0)
-	    memcpy (retval, &num[least_idx],
-		    RETURN_LIMB_SIZE * sizeof (mp_limb_t));
-	  else
-            {
-              for (i = least_idx; i < numsize - 1; ++i)
-                retval[i - least_idx] = (num[i] >> least_bit)
-                                        | (num[i + 1]
-                                           << (BITS_PER_MP_LIMB - least_bit));
-              if (i - least_idx < RETURN_LIMB_SIZE)
-                retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit;
-            }
-
-	  /* Check whether any limb beside the ones in RETVAL are non-zero.  */
-	  for (i = 0; num[i] == 0; ++i)
-	    ;
-
-	  return round_and_return (retval, bits - 1, negative,
-				   num[round_idx], round_bit,
-				   int_no < dig_no || i < round_idx);
-	  /* NOTREACHED */
-	}
-      else if (dig_no == int_no)
-	{
-	  const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-	  const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB;
-
-	  if (target_bit == is_bit)
-	    {
-	      memcpy (&retval[RETURN_LIMB_SIZE - numsize], num,
-		      numsize * sizeof (mp_limb_t));
-	      /* FIXME: the following loop can be avoided if we assume a
-		 maximal MANT_DIG value.  */
-	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
-	    }
-	  else if (target_bit > is_bit)
-	    {
-	      (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize],
-				   num, numsize, target_bit - is_bit);
-	      /* FIXME: the following loop can be avoided if we assume a
-		 maximal MANT_DIG value.  */
-	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
-	    }
-	  else
-	    {
-	      mp_limb_t cy;
-	      assert (numsize < RETURN_LIMB_SIZE);
-
-	      cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize],
-				 num, numsize, is_bit - target_bit);
-	      retval[RETURN_LIMB_SIZE - numsize - 1] = cy;
-	      /* FIXME: the following loop can be avoided if we assume a
-		 maximal MANT_DIG value.  */
-	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1);
-	    }
-
-	  return round_and_return (retval, bits - 1, negative, 0, 0, 0);
-	  /* NOTREACHED */
-	}
-
-      /* Store the bits we already have.  */
-      memcpy (retval, num, numsize * sizeof (mp_limb_t));
-#if RETURN_LIMB_SIZE > 1
-      if (numsize < RETURN_LIMB_SIZE)
-        retval[numsize] = 0;
-#endif
-    }
-
-  /* We have to compute at least some of the fractional digits.  */
-  {
-    /* We construct a fraction and the result of the division gives us
-       the needed digits.  The denominator is 1.0 multiplied by the
-       exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and
-       123e-6 gives 123 / 1000000.  */
-
-    int expbit;
-    int neg_exp;
-    int more_bits;
-    mp_limb_t cy;
-    mp_limb_t *psrc = den;
-    mp_limb_t *pdest = num;
-    const struct mp_power *ttab = &_fpioconst_pow10[0];
-
-    assert (dig_no > int_no && exponent <= 0);
-
-
-    /* For the fractional part we need not process too many digits.  One
-       decimal digits gives us log_2(10) ~ 3.32 bits.  If we now compute
-                        ceil(BITS / 3) =: N
-       digits we should have enough bits for the result.  The remaining
-       decimal digits give us the information that more bits are following.
-       This can be used while rounding.  (Two added as a safety margin.)  */
-    if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
-      {
-        dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
-        more_bits = 1;
-      }
-    else
-      more_bits = 0;
-
-    neg_exp = dig_no - int_no - exponent;
-
-    /* Construct the denominator.  */
-    densize = 0;
-    expbit = 1;
-    do
-      {
-	if ((neg_exp & expbit) != 0)
-	  {
-	    mp_limb_t cy;
-	    neg_exp ^= expbit;
-
-	    if (densize == 0)
-	      {
-		densize = ttab->arraysize - _FPIO_CONST_OFFSET;
-		memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET],
-			densize * sizeof (mp_limb_t));
-	      }
-	    else
-	      {
-		cy = __mpn_mul (pdest, &__tens[ttab->arrayoff
-					      + _FPIO_CONST_OFFSET],
-				ttab->arraysize - _FPIO_CONST_OFFSET,
-				psrc, densize);
-		densize += ttab->arraysize - _FPIO_CONST_OFFSET;
-		if (cy == 0)
-		  --densize;
-		(void) SWAP (psrc, pdest);
-	      }
-	  }
-	expbit <<= 1;
-	++ttab;
-      }
-    while (neg_exp != 0);
-
-    if (psrc == num)
-      memcpy (den, num, densize * sizeof (mp_limb_t));
-
-    /* Read the fractional digits from the string.  */
-    (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent
-#ifndef USE_WIDE_CHAR
-		       , decimal, decimal_len, thousands
-#endif
-		       );
-
-    /* We now have to shift both numbers so that the highest bit in the
-       denominator is set.  In the same process we copy the numerator to
-       a high place in the array so that the division constructs the wanted
-       digits.  This is done by a "quasi fix point" number representation.
-
-       num:   ddddddddddd . 0000000000000000000000
-              |--- m ---|
-       den:                            ddddddddddd      n >= m
-                                       |--- n ---|
-     */
-
-    count_leading_zeros (cnt, den[densize - 1]);
-
-    if (cnt > 0)
-      {
-	/* Don't call `mpn_shift' with a count of zero since the specification
-	   does not allow this.  */
-	(void) __mpn_lshift (den, den, densize, cnt);
-	cy = __mpn_lshift (num, num, numsize, cnt);
-	if (cy != 0)
-	  num[numsize++] = cy;
-      }
-
-    /* Now we are ready for the division.  But it is not necessary to
-       do a full multi-precision division because we only need a small
-       number of bits for the result.  So we do not use __mpn_divmod
-       here but instead do the division here by hand and stop whenever
-       the needed number of bits is reached.  The code itself comes
-       from the GNU MP Library by Torbj\"orn Granlund.  */
-
-    exponent = bits;
-
-    switch (densize)
-      {
-      case 1:
-	{
-	  mp_limb_t d, n, quot;
-	  int used = 0;
-
-	  n = num[0];
-	  d = den[0];
-	  assert (numsize == 1 && n < d);
-
-	  do
-	    {
-	      udiv_qrnnd (quot, n, n, 0, d);
-
-#define got_limb							      \
-	      if (bits == 0)						      \
-		{							      \
-		  register int cnt;					      \
-		  if (quot == 0)					      \
-		    cnt = BITS_PER_MP_LIMB;				      \
-		  else							      \
-		    count_leading_zeros (cnt, quot);			      \
-		  exponent -= cnt;					      \
-		  if (BITS_PER_MP_LIMB - cnt > MANT_DIG)		      \
-		    {							      \
-		      used = MANT_DIG + cnt;				      \
-		      retval[0] = quot >> (BITS_PER_MP_LIMB - used);	      \
-		      bits = MANT_DIG + 1;				      \
-		    }							      \
-		  else							      \
-		    {							      \
-		      /* Note that we only clear the second element.  */      \
-		      /* The conditional is determined at compile time.  */   \
-		      if (RETURN_LIMB_SIZE > 1)				      \
-			retval[1] = 0;					      \
-		      retval[0] = quot;					      \
-		      bits = -cnt;					      \
-		    }							      \
-		}							      \
-	      else if (bits + BITS_PER_MP_LIMB <= MANT_DIG)		      \
-		__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB,   \
-				quot);					      \
-	      else							      \
-		{							      \
-		  used = MANT_DIG - bits;				      \
-		  if (used > 0)						      \
-		    __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot);    \
-		}							      \
-	      bits += BITS_PER_MP_LIMB
-
-	      got_limb;
-	    }
-	  while (bits <= MANT_DIG);
-
-	  return round_and_return (retval, exponent - 1, negative,
-				   quot, BITS_PER_MP_LIMB - 1 - used,
-				   more_bits || n != 0);
-	}
-      case 2:
-	{
-	  mp_limb_t d0, d1, n0, n1;
-	  mp_limb_t quot = 0;
-	  int used = 0;
-
-	  d0 = den[0];
-	  d1 = den[1];
-
-	  if (numsize < densize)
-	    {
-	      if (num[0] >= d1)
-		{
-		  /* The numerator of the number occupies fewer bits than
-		     the denominator but the one limb is bigger than the
-		     high limb of the numerator.  */
-		  n1 = 0;
-		  n0 = num[0];
-		}
-	      else
-		{
-		  if (bits <= 0)
-		    exponent -= BITS_PER_MP_LIMB;
-		  else
-		    {
-		      if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
-			__mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
-					BITS_PER_MP_LIMB, 0);
-		      else
-			{
-			  used = MANT_DIG - bits;
-			  if (used > 0)
-			    __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
-			}
-		      bits += BITS_PER_MP_LIMB;
-		    }
-		  n1 = num[0];
-		  n0 = 0;
-		}
-	    }
-	  else
-	    {
-	      n1 = num[1];
-	      n0 = num[0];
-	    }
-
-	  while (bits <= MANT_DIG)
-	    {
-	      mp_limb_t r;
-
-	      if (n1 == d1)
-		{
-		  /* QUOT should be either 111..111 or 111..110.  We need
-		     special treatment of this rare case as normal division
-		     would give overflow.  */
-		  quot = ~(mp_limb_t) 0;
-
-		  r = n0 + d1;
-		  if (r < d1)	/* Carry in the addition?  */
-		    {
-		      add_ssaaaa (n1, n0, r - d0, 0, 0, d0);
-		      goto have_quot;
-		    }
-		  n1 = d0 - (d0 != 0);
-		  n0 = -d0;
-		}
-	      else
-		{
-		  udiv_qrnnd (quot, r, n1, n0, d1);
-		  umul_ppmm (n1, n0, d0, quot);
-		}
-
-	    q_test:
-	      if (n1 > r || (n1 == r && n0 > 0))
-		{
-		  /* The estimated QUOT was too large.  */
-		  --quot;
-
-		  sub_ddmmss (n1, n0, n1, n0, 0, d0);
-		  r += d1;
-		  if (r >= d1)	/* If not carry, test QUOT again.  */
-		    goto q_test;
-		}
-	      sub_ddmmss (n1, n0, r, 0, n1, n0);
-
-	    have_quot:
-	      got_limb;
-	    }
-
-	  return round_and_return (retval, exponent - 1, negative,
-				   quot, BITS_PER_MP_LIMB - 1 - used,
-				   more_bits || n1 != 0 || n0 != 0);
-	}
-      default:
-	{
-	  int i;
-	  mp_limb_t cy, dX, d1, n0, n1;
-	  mp_limb_t quot = 0;
-	  int used = 0;
-
-	  dX = den[densize - 1];
-	  d1 = den[densize - 2];
-
-	  /* The division does not work if the upper limb of the two-limb
-	     numerator is greater than the denominator.  */
-	  if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0)
-	    num[numsize++] = 0;
-
-	  if (numsize < densize)
-	    {
-	      mp_size_t empty = densize - numsize;
-
-	      if (bits <= 0)
-		{
-		  register int i;
-		  for (i = numsize; i > 0; --i)
-		    num[i + empty] = num[i - 1];
-		  MPN_ZERO (num, empty + 1);
-		  exponent -= empty * BITS_PER_MP_LIMB;
-		}
-	      else
-		{
-		  if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG)
-		    {
-		      /* We make a difference here because the compiler
-			 cannot optimize the `else' case that good and
-			 this reflects all currently used FLOAT types
-			 and GMP implementations.  */
-		      register int i;
-#if RETURN_LIMB_SIZE <= 2
-		      assert (empty == 1);
-		      __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
-				      BITS_PER_MP_LIMB, 0);
-#else
-		      for (i = RETURN_LIMB_SIZE; i > empty; --i)
-			retval[i] = retval[i - empty];
-#endif
-		      for (i = numsize; i > 0; --i)
-			num[i + empty] = num[i - 1];
-		      MPN_ZERO (num, empty + 1);
-		    }
-		  else
-		    {
-		      used = MANT_DIG - bits;
-		      if (used >= BITS_PER_MP_LIMB)
-			{
-			  register int i;
-			  (void) __mpn_lshift (&retval[used
-						       / BITS_PER_MP_LIMB],
-					       retval, RETURN_LIMB_SIZE,
-					       used % BITS_PER_MP_LIMB);
-			  for (i = used / BITS_PER_MP_LIMB; i >= 0; --i)
-			    retval[i] = 0;
-			}
-		      else if (used > 0)
-			__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
-		    }
-		  bits += empty * BITS_PER_MP_LIMB;
-		}
-	    }
-	  else
-	    {
-	      int i;
-	      assert (numsize == densize);
-	      for (i = numsize; i > 0; --i)
-		num[i] = num[i - 1];
-	    }
-
-	  den[densize] = 0;
-	  n0 = num[densize];
-
-	  while (bits <= MANT_DIG)
-	    {
-	      if (n0 == dX)
-		/* This might over-estimate QUOT, but it's probably not
-		   worth the extra code here to find out.  */
-		quot = ~(mp_limb_t) 0;
-	      else
-		{
-		  mp_limb_t r;
-
-		  udiv_qrnnd (quot, r, n0, num[densize - 1], dX);
-		  umul_ppmm (n1, n0, d1, quot);
-
-		  while (n1 > r || (n1 == r && n0 > num[densize - 2]))
-		    {
-		      --quot;
-		      r += dX;
-		      if (r < dX) /* I.e. "carry in previous addition?" */
-			break;
-		      n1 -= n0 < d1;
-		      n0 -= d1;
-		    }
-		}
-
-	      /* Possible optimization: We already have (q * n0) and (1 * n1)
-		 after the calculation of QUOT.  Taking advantage of this, we
-		 could make this loop make two iterations less.  */
-
-	      cy = __mpn_submul_1 (num, den, densize + 1, quot);
-
-	      if (num[densize] != cy)
-		{
-		  cy = __mpn_add_n (num, num, den, densize);
-		  assert (cy != 0);
-		  --quot;
-		}
-	      n0 = num[densize] = num[densize - 1];
-	      for (i = densize - 1; i > 0; --i)
-		num[i] = num[i - 1];
-
-	      got_limb;
-	    }
-
-	  for (i = densize; num[i] == 0 && i >= 0; --i)
-	    ;
-	  return round_and_return (retval, exponent - 1, negative,
-				   quot, BITS_PER_MP_LIMB - 1 - used,
-				   more_bits || i >= 0);
-	}
-      }
-  }
-
-  /* NOTREACHED */
+  return INTERNAL(STRTOF_L) (nptr, endptr, group, _NL_CURRENT_LOCALE);
 }
-#if defined _LIBC \
-    && !(defined USE_IN_EXTENDED_LOCALE_MODEL && defined USE_WIDE_CHAR)
+#if defined _LIBC
 libc_hidden_def (INTERNAL (STRTOF))
 #endif
-
-/* External user entry point.  */
+
 
 FLOAT
 #ifdef weak_function
 weak_function
 #endif
-STRTOF (nptr, endptr LOCALE_PARAM)
+STRTOF (nptr, endptr)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
-     LOCALE_PARAM_DECL
 {
-  return INTERNAL (STRTOF) (nptr, endptr, 0 LOCALE_PARAM);
+  return INTERNAL(STRTOF_L) (nptr, endptr, 0, _NL_CURRENT_LOCALE);
 }
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index e8449050d3..89d30b435b 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to float value, using given locale.
-   Copyright (C) 1997,98,2002 Free Software Foundation, Inc.
+   Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,14 +18,1555 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
-
 #include <xlocale.h>
 
 extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
 extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 						       int, int, __locale_t);
 
-#include <strtod.c>
+/* Configuration part.  These macros are defined by `strtold.c',
+   `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the
+   `long double' and `float' versions of the reader.  */
+#ifndef FLOAT
+# define FLOAT		double
+# define FLT		DBL
+# ifdef USE_WIDE_CHAR
+#  define STRTOF	wcstod_l
+#  define __STRTOF	__wcstod_l
+# else
+#  define STRTOF	strtod_l
+#  define __STRTOF	__strtod_l
+# endif
+# define MPN2FLOAT	__mpn_construct_double
+# define FLOAT_HUGE_VAL	HUGE_VAL
+# define SET_MANTISSA(flt, mant) \
+  do { union ieee754_double u;						      \
+       u.d = (flt);							      \
+       if ((mant & 0xfffffffffffffULL) == 0)				      \
+	 mant = 0x8000000000000ULL;					      \
+       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
+       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
+       (flt) = u.d;							      \
+  } while (0)
+#endif
+/* End of configuration part.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <ieee754.h>
+#include "../locale/localeinfo.h"
+#include <locale.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The gmp headers need some configuration frobs.  */
+#define HAVE_ALLOCA 1
+
+/* Include gmp-mparam.h first, such that definitions of _SHORT_LIMB
+   and _LONG_LONG_LIMB in it can take effect into gmp.h.  */
+#include <gmp-mparam.h>
+#include <gmp.h>
+#include <gmp-impl.h>
+#include <longlong.h>
+#include "fpioconst.h"
+
+#define NDEBUG 1
+#include <assert.h>
+
+
+/* We use this code for the extended locale handling where the
+   function gets as an additional argument the locale which has to be
+   used.  To access the values we have to redefine the _NL_CURRENT and
+   _NL_CURRENT_WORD macros.  */
+#undef _NL_CURRENT
+#define _NL_CURRENT(category, item) \
+  (current->values[_NL_ITEM_INDEX (item)].string)
+#undef _NL_CURRENT_WORD
+#define _NL_CURRENT_WORD(category, item) \
+  ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define STRING_TYPE wchar_t
+# define CHAR_TYPE wint_t
+# define L_(Ch) L##Ch
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc)
+# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc)
+# define TOLOWER(Ch) __towlower_l ((Ch), loc)
+# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc)
+# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
+#else
+# define STRING_TYPE char
+# define CHAR_TYPE char
+# define L_(Ch) Ch
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISDIGIT(Ch) __isdigit_l ((Ch), loc)
+# define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc)
+# define TOLOWER(Ch) __tolower_l ((Ch), loc)
+# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc)
+# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
+#endif
+
+
+/* Constants we need from float.h; select the set for the FLOAT precision.  */
+#define MANT_DIG	PASTE(FLT,_MANT_DIG)
+#define	DIG		PASTE(FLT,_DIG)
+#define	MAX_EXP		PASTE(FLT,_MAX_EXP)
+#define	MIN_EXP		PASTE(FLT,_MIN_EXP)
+#define MAX_10_EXP	PASTE(FLT,_MAX_10_EXP)
+#define MIN_10_EXP	PASTE(FLT,_MIN_10_EXP)
+
+/* Extra macros required to get FLT expanded before the pasting.  */
+#define PASTE(a,b)	PASTE1(a,b)
+#define PASTE1(a,b)	a##b
+
+/* Function to construct a floating point number from an MP integer
+   containing the fraction bits, a base 2 exponent, and a sign flag.  */
+extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
+
+/* Definitions according to limb size used.  */
+#if	BITS_PER_MP_LIMB == 32
+# define MAX_DIG_PER_LIMB	9
+# define MAX_FAC_PER_LIMB	1000000000UL
+#elif	BITS_PER_MP_LIMB == 64
+# define MAX_DIG_PER_LIMB	19
+# define MAX_FAC_PER_LIMB	10000000000000000000ULL
+#else
+# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+
+/* Local data structure.  */
+static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
+{    0,                   10,                   100,
+     1000,                10000,                100000L,
+     1000000L,            10000000L,            100000000L,
+     1000000000L
+#if BITS_PER_MP_LIMB > 32
+	        ,	  10000000000ULL,       100000000000ULL,
+     1000000000000ULL,    10000000000000ULL,    100000000000000ULL,
+     1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
+     1000000000000000000ULL, 10000000000000000000ULL
+#endif
+#if BITS_PER_MP_LIMB > 64
+  #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
+#endif
+};
+
+#ifndef	howmany
+#define	howmany(x,y)		(((x)+((y)-1))/(y))
+#endif
+#define SWAP(x, y)		({ typeof(x) _tmp = x; x = y; y = _tmp; })
+
+#define NDIG			(MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG)
+#define HEXNDIG			((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG)
+#define	RETURN_LIMB_SIZE		howmany (MANT_DIG, BITS_PER_MP_LIMB)
+
+#define RETURN(val,end)							      \
+    do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end);		      \
+	 return val; } while (0)
+
+/* Maximum size necessary for mpn integers to hold floating point numbers.  */
+#define	MPNSIZE		(howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \
+			 + 2)
+/* Declare an mpn integer variable that big.  */
+#define	MPN_VAR(name)	mp_limb_t name[MPNSIZE]; mp_size_t name##size
+/* Copy an mpn integer value.  */
+#define MPN_ASSIGN(dst, src) \
+	memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t))
+
+
+/* Return a floating point number of the needed type according to the given
+   multi-precision number after possible rounding.  */
+static FLOAT
+round_and_return (mp_limb_t *retval, int exponent, int negative,
+		  mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
+{
+  if (exponent < MIN_EXP - 1)
+    {
+      mp_size_t shift = MIN_EXP - 1 - exponent;
+
+      if (shift > MANT_DIG)
+	{
+	  __set_errno (EDOM);
+	  return 0.0;
+	}
+
+      more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
+      if (shift == MANT_DIG)
+	/* This is a special case to handle the very seldom case where
+	   the mantissa will be empty after the shift.  */
+	{
+	  int i;
+
+	  round_limb = retval[RETURN_LIMB_SIZE - 1];
+	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+	    more_bits |= retval[i] != 0;
+	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
+	}
+      else if (shift >= BITS_PER_MP_LIMB)
+	{
+	  int i;
+
+	  round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
+	  round_bit = (shift - 1) % BITS_PER_MP_LIMB;
+	  for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i)
+	    more_bits |= retval[i] != 0;
+	  more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1))
+			!= 0);
+
+	  (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
+                               RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+                               shift % BITS_PER_MP_LIMB);
+          MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
+                    shift / BITS_PER_MP_LIMB);
+	}
+      else if (shift > 0)
+	{
+          round_limb = retval[0];
+          round_bit = shift - 1;
+	  (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
+	}
+      /* This is a hook for the m68k long double format, where the
+	 exponent bias is the same for normalized and denormalized
+	 numbers.  */
+#ifndef DENORM_EXP
+# define DENORM_EXP (MIN_EXP - 2)
+#endif
+      exponent = DENORM_EXP;
+    }
+
+  if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
+      && (more_bits || (retval[0] & 1) != 0
+          || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
+    {
+      mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
+
+      if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) ||
+          ((MANT_DIG % BITS_PER_MP_LIMB) != 0 &&
+           (retval[RETURN_LIMB_SIZE - 1]
+            & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0))
+	{
+	  ++exponent;
+	  (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1);
+	  retval[RETURN_LIMB_SIZE - 1]
+	    |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB);
+	}
+      else if (exponent == DENORM_EXP
+	       && (retval[RETURN_LIMB_SIZE - 1]
+		   & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB)))
+	       != 0)
+	  /* The number was denormalized but now normalized.  */
+	exponent = MIN_EXP - 1;
+    }
+
+  if (exponent > MAX_EXP)
+    return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+
+  return MPN2FLOAT (retval, exponent, negative);
+}
+
+
+/* Read a multi-precision integer starting at STR with exactly DIGCNT digits
+   into N.  Return the size of the number limbs in NSIZE at the first
+   character od the string that is not part of the integer as the function
+   value.  If the EXPONENT is small enough to be taken as an additional
+   factor for the resulting number (see code) multiply by it.  */
+static const STRING_TYPE *
+str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+	    int *exponent
+#ifndef USE_WIDE_CHAR
+	    , const char *decimal, size_t decimal_len, const char *thousands
+#endif
+
+	    )
+{
+  /* Number of digits for actual limb.  */
+  int cnt = 0;
+  mp_limb_t low = 0;
+  mp_limb_t start;
+
+  *nsize = 0;
+  assert (digcnt > 0);
+  do
+    {
+      if (cnt == MAX_DIG_PER_LIMB)
+	{
+	  if (*nsize == 0)
+	    {
+	      n[0] = low;
+	      *nsize = 1;
+	    }
+	  else
+	    {
+	      mp_limb_t cy;
+	      cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB);
+	      cy += __mpn_add_1 (n, n, *nsize, low);
+	      if (cy != 0)
+		{
+		  n[*nsize] = cy;
+		  ++(*nsize);
+		}
+	    }
+	  cnt = 0;
+	  low = 0;
+	}
+
+      /* There might be thousands separators or radix characters in
+	 the string.  But these all can be ignored because we know the
+	 format of the number is correct and we have an exact number
+	 of characters to read.  */
+#ifdef USE_WIDE_CHAR
+      if (*str < L'0' || *str > L'9')
+	++str;
+#else
+      if (*str < '0' || *str > '9')
+	{
+	  int inner = 0;
+	  if (thousands != NULL && *str == *thousands
+	      && ({ for (inner = 1; thousands[inner] != '\0'; ++inner)
+		      if (thousands[inner] != str[inner])
+			break;
+		    thousands[inner] == '\0'; }))
+	    str += inner;
+	  else
+	    str += decimal_len;
+	}
+#endif
+      low = low * 10 + *str++ - L_('0');
+      ++cnt;
+    }
+  while (--digcnt > 0);
+
+  if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
+    {
+      low *= _tens_in_limb[*exponent];
+      start = _tens_in_limb[cnt + *exponent];
+      *exponent = 0;
+    }
+  else
+    start = _tens_in_limb[cnt];
+
+  if (*nsize == 0)
+    {
+      n[0] = low;
+      *nsize = 1;
+    }
+  else
+    {
+      mp_limb_t cy;
+      cy = __mpn_mul_1 (n, n, *nsize, start);
+      cy += __mpn_add_1 (n, n, *nsize, low);
+      if (cy != 0)
+	n[(*nsize)++] = cy;
+    }
+
+  return str;
+}
+
+
+/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits
+   with the COUNT most significant bits of LIMB.
+
+   Tege doesn't like this function so I have to write it here myself. :)
+   --drepper */
+static inline void
+__attribute ((always_inline))
+__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
+		mp_limb_t limb)
+{
+  if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB)
+    {
+      /* Optimize the case of shifting by exactly a word:
+	 just copy words, with no actual bit-shifting.  */
+      mp_size_t i;
+      for (i = size - 1; i > 0; --i)
+	ptr[i] = ptr[i - 1];
+      ptr[0] = limb;
+    }
+  else
+    {
+      (void) __mpn_lshift (ptr, ptr, size, count);
+      ptr[0] |= limb >> (BITS_PER_MP_LIMB - count);
+    }
+}
+
+
+#define INTERNAL(x) INTERNAL1(x)
+#define INTERNAL1(x) __##x##_internal
+
+/* This file defines a function to check for correct grouping.  */
+#include "grouping.h"
+
+
+/* Return a floating point number with the value of the given string NPTR.
+   Set *ENDPTR to the character after the last used one.  If the number is
+   smaller than the smallest representable number, set `errno' to ERANGE and
+   return 0.0.  If the number is too big to be represented, set `errno' to
+   ERANGE and return HUGE_VAL with the appropriate sign.  */
+FLOAT
+INTERNAL (__STRTOF) (nptr, endptr, group, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int group;
+     __locale_t loc;
+{
+  int negative;			/* The sign of the number.  */
+  MPN_VAR (num);		/* MP representation of the number.  */
+  int exponent;			/* Exponent of the number.  */
+
+  /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
+  int base = 10;
+
+  /* When we have to compute fractional digits we form a fraction with a
+     second multi-precision number (and we sometimes need a second for
+     temporary results).  */
+  MPN_VAR (den);
+
+  /* Representation for the return value.  */
+  mp_limb_t retval[RETURN_LIMB_SIZE];
+  /* Number of bits currently in result value.  */
+  int bits;
+
+  /* Running pointer after the last character processed in the string.  */
+  const STRING_TYPE *cp, *tp;
+  /* Start of significant part of the number.  */
+  const STRING_TYPE *startp, *start_of_digits;
+  /* Points at the character following the integer and fractional digits.  */
+  const STRING_TYPE *expp;
+  /* Total number of digit and number of digits in integer part.  */
+  int dig_no, int_no, lead_zero;
+  /* Contains the last character read.  */
+  CHAR_TYPE c;
+
+/* We should get wint_t from <stddef.h>, but not all GCC versions define it
+   there.  So define it ourselves if it remains undefined.  */
+#ifndef _WINT_T
+  typedef unsigned int wint_t;
+#endif
+  /* The radix character of the current locale.  */
+#ifdef USE_WIDE_CHAR
+  wchar_t decimal;
+#else
+  const char *decimal;
+  size_t decimal_len;
+#endif
+  /* The thousands character of the current locale.  */
+#ifdef USE_WIDE_CHAR
+  wchar_t thousands = L'\0';
+#else
+  const char *thousands = NULL;
+#endif
+  /* The numeric grouping specification of the current locale,
+     in the format described in <locale.h>.  */
+  const char *grouping;
+  /* Used in several places.  */
+  int cnt;
+
+  struct locale_data *current = loc->__locales[LC_NUMERIC];
+
+  if (group)
+    {
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+#ifdef USE_WIDE_CHAR
+	  thousands = _NL_CURRENT_WORD (LC_NUMERIC,
+					_NL_NUMERIC_THOUSANDS_SEP_WC);
+	  if (thousands == L'\0')
+	    grouping = NULL;
+#else
+	  thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+	  if (*thousands == '\0')
+	    {
+	      thousands = NULL;
+	      grouping = NULL;
+	    }
+#endif
+	}
+    }
+  else
+    grouping = NULL;
+
+  /* Find the locale's decimal point character.  */
+#ifdef USE_WIDE_CHAR
+  decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
+  assert (decimal != L'\0');
+# define decimal_len 1
+#else
+  decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+  decimal_len = strlen (decimal);
+  assert (decimal_len > 0);
+#endif
+
+  /* Prepare number representation.  */
+  exponent = 0;
+  negative = 0;
+  bits = 0;
+
+  /* Parse string to get maximal legal prefix.  We need the number of
+     characters of the integer part, the fractional part and the exponent.  */
+  cp = nptr - 1;
+  /* Ignore leading white space.  */
+  do
+    c = *++cp;
+  while (ISSPACE (c));
+
+  /* Get sign of the result.  */
+  if (c == L_('-'))
+    {
+      negative = 1;
+      c = *++cp;
+    }
+  else if (c == L_('+'))
+    c = *++cp;
+
+  /* Return 0.0 if no legal string is found.
+     No character is used even if a sign was found.  */
+#ifdef USE_WIDE_CHAR
+  if (c == (wint_t) decimal
+      && (wint_t) cp[1] >= L'0' && (wint_t) cp[1] <= L'9')
+    {
+      /* We accept it.  This funny construct is here only to indent
+	 the code directly.  */
+    }
+#else
+  for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+    if (cp[cnt] != decimal[cnt])
+      break;
+  if (decimal[cnt] == '\0' && cp[cnt] >= '0' && cp[cnt] <= '9')
+    {
+      /* We accept it.  This funny construct is here only to indent
+	 the code directly.  */
+    }
+#endif
+  else if (c < L_('0') || c > L_('9'))
+    {
+      /* Check for `INF' or `INFINITY'.  */
+      if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
+	{
+	  /* Return +/- infinity.  */
+	  if (endptr != NULL)
+	    *endptr = (STRING_TYPE *)
+		      (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0
+			     ? 8 : 3));
+
+	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+	}
+
+      if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
+	{
+	  /* Return NaN.  */
+	  FLOAT retval = NAN;
+
+	  cp += 3;
+
+	  /* Match `(n-char-sequence-digit)'.  */
+	  if (*cp == L_('('))
+	    {
+	      const STRING_TYPE *startp = cp;
+	      do
+		++cp;
+	      while ((*cp >= L_('0') && *cp <= L_('9'))
+		     || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z'))
+		     || *cp == L_('_'));
+
+	      if (*cp != L_(')'))
+		/* The closing brace is missing.  Only match the NAN
+		   part.  */
+		cp = startp;
+	      else
+		{
+		  /* This is a system-dependent way to specify the
+		     bitmask used for the NaN.  We expect it to be
+		     a number which is put in the mantissa of the
+		     number.  */
+		  STRING_TYPE *endp;
+		  unsigned long long int mant;
+
+		  mant = STRTOULL (startp + 1, &endp, 0);
+		  if (endp == cp)
+		    SET_MANTISSA (retval, mant);
+		}
+	    }
+
+	  if (endptr != NULL)
+	    *endptr = (STRING_TYPE *) cp;
+
+	  return retval;
+	}
+
+      /* It is really a text we do not recognize.  */
+      RETURN (0.0, nptr);
+    }
+
+  /* First look whether we are faced with a hexadecimal number.  */
+  if (c == L_('0') && TOLOWER (cp[1]) == L_('x'))
+    {
+      /* Okay, it is a hexa-decimal number.  Remember this and skip
+	 the characters.  BTW: hexadecimal numbers must not be
+	 grouped.  */
+      base = 16;
+      cp += 2;
+      c = *cp;
+      grouping = NULL;
+    }
+
+  /* Record the start of the digits, in case we will check their grouping.  */
+  start_of_digits = startp = cp;
+
+  /* Ignore leading zeroes.  This helps us to avoid useless computations.  */
+#ifdef USE_WIDE_CHAR
+  while (c == L'0' || ((wint_t) thousands != L'\0' && c == (wint_t) thousands))
+    c = *++cp;
+#else
+  if (thousands == NULL)
+    while (c == '0')
+      c = *++cp;
+  else
+    {
+      /* We also have the multibyte thousands string.  */
+      while (1)
+	{
+	  if (c != '0')
+	    {
+	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+		if (c != thousands[cnt])
+		  break;
+	      if (thousands[cnt] != '\0')
+		break;
+	    }
+	  c = *++cp;
+	}
+    }
+#endif
+
+  /* If no other digit but a '0' is found the result is 0.0.
+     Return current read pointer.  */
+  if ((c < L_('0') || c > L_('9'))
+      && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
+			 || c > (CHAR_TYPE) TOLOWER (L_('f'))))
+#ifdef USE_WIDE_CHAR
+      && c != (wint_t) decimal
+#else
+      && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+	      if (decimal[cnt] != cp[cnt])
+		break;
+	    decimal[cnt] != '\0'; })
+#endif
+      && (base == 16 && (cp == start_of_digits
+			 || (CHAR_TYPE) TOLOWER (c) != L_('p')))
+      && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
+    {
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
+      /* If TP is at the start of the digits, there was no correctly
+	 grouped prefix of the string; so no number found.  */
+      RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
+    }
+
+  /* Remember first significant digit and read following characters until the
+     decimal point, exponent character or any non-FP number character.  */
+  startp = cp;
+  dig_no = 0;
+  while (1)
+    {
+      if ((c >= L_('0') && c <= L_('9'))
+	  || (base == 16 && (wint_t) TOLOWER (c) >= L_('a')
+	      && (wint_t) TOLOWER (c) <= L_('f')))
+	++dig_no;
+      else
+	{
+#ifdef USE_WIDE_CHAR
+	  if ((wint_t) thousands == L'\0' || c != (wint_t) thousands)
+	    /* Not a digit or separator: end of the integer part.  */
+	    break;
+#else
+	  if (thousands == NULL)
+	    break;
+	  else
+	    {
+	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+		if (thousands[cnt] != cp[cnt])
+		  break;
+	      if (thousands[cnt] != '\0')
+		break;
+	    }
+#endif
+	}
+      c = *++cp;
+    }
+
+  if (grouping && dig_no > 0)
+    {
+      /* Check the grouping of the digits.  */
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
+      if (cp != tp)
+        {
+	  /* Less than the entire string was correctly grouped.  */
+
+	  if (tp == start_of_digits)
+	    /* No valid group of numbers at all: no valid number.  */
+	    RETURN (0.0, nptr);
+
+	  if (tp < startp)
+	    /* The number is validly grouped, but consists
+	       only of zeroes.  The whole value is zero.  */
+	    RETURN (0.0, tp);
+
+	  /* Recompute DIG_NO so we won't read more digits than
+	     are properly grouped.  */
+	  cp = tp;
+	  dig_no = 0;
+	  for (tp = startp; tp < cp; ++tp)
+	    if (*tp >= L_('0') && *tp <= L_('9'))
+	      ++dig_no;
+
+	  int_no = dig_no;
+	  lead_zero = 0;
+
+	  goto number_parsed;
+	}
+    }
+
+  /* We have the number digits in the integer part.  Whether these are all or
+     any is really a fractional digit will be decided later.  */
+  int_no = dig_no;
+  lead_zero = int_no == 0 ? -1 : 0;
+
+  /* Read the fractional digits.  A special case are the 'american style'
+     numbers like `16.' i.e. with decimal but without trailing digits.  */
+  if (
+#ifdef USE_WIDE_CHAR
+      c == (wint_t) decimal
+#else
+      ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+	   if (decimal[cnt] != cp[cnt])
+	     break;
+	 decimal[cnt] == '\0'; })
+#endif
+      )
+    {
+      cp += decimal_len;
+      c = *cp;
+      while ((c >= L_('0') && c <= L_('9')) ||
+	     (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
+	{
+	  if (c != L_('0') && lead_zero == -1)
+	    lead_zero = dig_no - int_no;
+	  ++dig_no;
+	  c = *++cp;
+	}
+    }
+
+  /* Remember start of exponent (if any).  */
+  expp = cp;
+
+  /* Read exponent.  */
+  if ((base == 16 && TOLOWER (c) == L_('p'))
+      || (base != 16 && TOLOWER (c) == L_('e')))
+    {
+      int exp_negative = 0;
+
+      c = *++cp;
+      if (c == L_('-'))
+	{
+	  exp_negative = 1;
+	  c = *++cp;
+	}
+      else if (c == L_('+'))
+	c = *++cp;
+
+      if (c >= L_('0') && c <= L_('9'))
+	{
+	  int exp_limit;
+
+	  /* Get the exponent limit. */
+	  if (base == 16)
+	    exp_limit = (exp_negative ?
+			 -MIN_EXP + MANT_DIG + 4 * int_no :
+			 MAX_EXP - 4 * int_no + lead_zero);
+	  else
+	    exp_limit = (exp_negative ?
+			 -MIN_10_EXP + MANT_DIG + int_no :
+			 MAX_10_EXP - int_no + lead_zero);
+
+	  do
+	    {
+	      exponent *= 10;
+
+	      if (exponent > exp_limit)
+		/* The exponent is too large/small to represent a valid
+		   number.  */
+		{
+	 	  FLOAT result;
+
+		  /* We have to take care for special situation: a joker
+		     might have written "0.0e100000" which is in fact
+		     zero.  */
+		  if (lead_zero == -1)
+		    result = negative ? -0.0 : 0.0;
+		  else
+		    {
+		      /* Overflow or underflow.  */
+		      __set_errno (ERANGE);
+		      result = (exp_negative ? 0.0 :
+				negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+		    }
+
+		  /* Accept all following digits as part of the exponent.  */
+		  do
+		    ++cp;
+		  while (*cp >= L_('0') && *cp <= L_('9'));
+
+		  RETURN (result, cp);
+		  /* NOTREACHED */
+		}
+
+	      exponent += c - L_('0');
+	      c = *++cp;
+	    }
+	  while (c >= L_('0') && c <= L_('9'));
+
+	  if (exp_negative)
+	    exponent = -exponent;
+	}
+      else
+	cp = expp;
+    }
+
+  /* We don't want to have to work with trailing zeroes after the radix.  */
+  if (dig_no > int_no)
+    {
+      while (expp[-1] == L_('0'))
+	{
+	  --expp;
+	  --dig_no;
+	}
+      assert (dig_no >= int_no);
+    }
+
+  if (dig_no == int_no && dig_no > 0 && exponent < 0)
+    do
+      {
+	while (! (base == 16 ? ISXDIGIT (expp[-1]) : ISDIGIT (expp[-1])))
+	  --expp;
+
+	if (expp[-1] != L_('0'))
+	  break;
+
+	--expp;
+	--dig_no;
+	--int_no;
+	++exponent;
+      }
+    while (dig_no > 0 && exponent < 0);
+
+ number_parsed:
+
+  /* The whole string is parsed.  Store the address of the next character.  */
+  if (endptr)
+    *endptr = (STRING_TYPE *) cp;
+
+  if (dig_no == 0)
+    return negative ? -0.0 : 0.0;
+
+  if (lead_zero)
+    {
+      /* Find the decimal point */
+#ifdef USE_WIDE_CHAR
+      while (*startp != decimal)
+	++startp;
+#else
+      while (1)
+	{
+	  if (*startp == decimal[0])
+	    {
+	      for (cnt = 1; decimal[cnt] != '\0'; ++cnt)
+		if (decimal[cnt] != startp[cnt])
+		  break;
+	      if (decimal[cnt] == '\0')
+		break;
+	    }
+	  ++startp;
+	}
+#endif
+      startp += lead_zero + decimal_len;
+      exponent -= base == 16 ? 4 * lead_zero : lead_zero;
+      dig_no -= lead_zero;
+    }
+
+  /* If the BASE is 16 we can use a simpler algorithm.  */
+  if (base == 16)
+    {
+      static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3,
+				     4, 4, 4, 4, 4, 4, 4, 4 };
+      int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB;
+      int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+      mp_limb_t val;
+
+      while (!ISXDIGIT (*startp))
+	++startp;
+      while (*startp == L_('0'))
+	++startp;
+      if (ISDIGIT (*startp))
+	val = *startp++ - L_('0');
+      else
+	val = 10 + TOLOWER (*startp++) - L_('a');
+      bits = nbits[val];
+      /* We cannot have a leading zero.  */
+      assert (bits != 0);
+
+      if (pos + 1 >= 4 || pos + 1 >= bits)
+	{
+	  /* We don't have to care for wrapping.  This is the normal
+	     case so we add the first clause in the `if' expression as
+	     an optimization.  It is a compile-time constant and so does
+	     not cost anything.  */
+	  retval[idx] = val << (pos - bits + 1);
+	  pos -= bits;
+	}
+      else
+	{
+	  retval[idx--] = val >> (bits - pos - 1);
+	  retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1));
+	  pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1);
+	}
+
+      /* Adjust the exponent for the bits we are shifting in.  */
+      exponent += bits - 1 + (int_no - 1) * 4;
+
+      while (--dig_no > 0 && idx >= 0)
+	{
+	  if (!ISXDIGIT (*startp))
+	    startp += decimal_len;
+	  if (ISDIGIT (*startp))
+	    val = *startp++ - L_('0');
+	  else
+	    val = 10 + TOLOWER (*startp++) - L_('a');
+
+	  if (pos + 1 >= 4)
+	    {
+	      retval[idx] |= val << (pos - 4 + 1);
+	      pos -= 4;
+	    }
+	  else
+	    {
+	      retval[idx--] |= val >> (4 - pos - 1);
+	      val <<= BITS_PER_MP_LIMB - (4 - pos - 1);
+	      if (idx < 0)
+		return round_and_return (retval, exponent, negative, val,
+					 BITS_PER_MP_LIMB - 1, dig_no > 0);
+
+	      retval[idx] = val;
+	      pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1);
+	    }
+	}
+
+      /* We ran out of digits.  */
+      MPN_ZERO (retval, idx);
+
+      return round_and_return (retval, exponent, negative, 0, 0, 0);
+    }
+
+  /* Now we have the number of digits in total and the integer digits as well
+     as the exponent and its sign.  We can decide whether the read digits are
+     really integer digits or belong to the fractional part; i.e. we normalize
+     123e-2 to 1.23.  */
+  {
+    register int incr = (exponent < 0 ? MAX (-int_no, exponent)
+			 : MIN (dig_no - int_no, exponent));
+    int_no += incr;
+    exponent -= incr;
+  }
+
+  if (int_no + exponent > MAX_10_EXP + 1)
+    {
+      __set_errno (ERANGE);
+      return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+    }
+
+  if (exponent < MIN_10_EXP - (DIG + 1))
+    {
+      __set_errno (ERANGE);
+      return 0.0;
+    }
+
+  if (int_no > 0)
+    {
+      /* Read the integer part as a multi-precision number to NUM.  */
+      startp = str_to_mpn (startp, int_no, num, &numsize, &exponent
+#ifndef USE_WIDE_CHAR
+			   , decimal, decimal_len, thousands
+#endif
+			   );
+
+      if (exponent > 0)
+	{
+	  /* We now multiply the gained number by the given power of ten.  */
+	  mp_limb_t *psrc = num;
+	  mp_limb_t *pdest = den;
+	  int expbit = 1;
+	  const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+	  do
+	    {
+	      if ((exponent & expbit) != 0)
+		{
+		  size_t size = ttab->arraysize - _FPIO_CONST_OFFSET;
+		  mp_limb_t cy;
+		  exponent ^= expbit;
+
+		  /* FIXME: not the whole multiplication has to be
+		     done.  If we have the needed number of bits we
+		     only need the information whether more non-zero
+		     bits follow.  */
+		  if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET)
+		    cy = __mpn_mul (pdest, psrc, numsize,
+				    &__tens[ttab->arrayoff
+					   + _FPIO_CONST_OFFSET],
+				    size);
+		  else
+		    cy = __mpn_mul (pdest, &__tens[ttab->arrayoff
+						  + _FPIO_CONST_OFFSET],
+				    size, psrc, numsize);
+		  numsize += size;
+		  if (cy == 0)
+		    --numsize;
+		  (void) SWAP (psrc, pdest);
+		}
+	      expbit <<= 1;
+	      ++ttab;
+	    }
+	  while (exponent != 0);
+
+	  if (psrc == den)
+	    memcpy (num, den, numsize * sizeof (mp_limb_t));
+	}
+
+      /* Determine how many bits of the result we already have.  */
+      count_leading_zeros (bits, num[numsize - 1]);
+      bits = numsize * BITS_PER_MP_LIMB - bits;
+
+      /* Now we know the exponent of the number in base two.
+	 Check it against the maximum possible exponent.  */
+      if (bits > MAX_EXP)
+	{
+	  __set_errno (ERANGE);
+	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+	}
+
+      /* We have already the first BITS bits of the result.  Together with
+	 the information whether more non-zero bits follow this is enough
+	 to determine the result.  */
+      if (bits > MANT_DIG)
+	{
+	  int i;
+	  const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB;
+	  const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB;
+	  const mp_size_t round_idx = least_bit == 0 ? least_idx - 1
+						     : least_idx;
+	  const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1
+						     : least_bit - 1;
+
+	  if (least_bit == 0)
+	    memcpy (retval, &num[least_idx],
+		    RETURN_LIMB_SIZE * sizeof (mp_limb_t));
+	  else
+            {
+              for (i = least_idx; i < numsize - 1; ++i)
+                retval[i - least_idx] = (num[i] >> least_bit)
+                                        | (num[i + 1]
+                                           << (BITS_PER_MP_LIMB - least_bit));
+              if (i - least_idx < RETURN_LIMB_SIZE)
+                retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit;
+            }
+
+	  /* Check whether any limb beside the ones in RETVAL are non-zero.  */
+	  for (i = 0; num[i] == 0; ++i)
+	    ;
+
+	  return round_and_return (retval, bits - 1, negative,
+				   num[round_idx], round_bit,
+				   int_no < dig_no || i < round_idx);
+	  /* NOTREACHED */
+	}
+      else if (dig_no == int_no)
+	{
+	  const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+	  const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB;
+
+	  if (target_bit == is_bit)
+	    {
+	      memcpy (&retval[RETURN_LIMB_SIZE - numsize], num,
+		      numsize * sizeof (mp_limb_t));
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+	    }
+	  else if (target_bit > is_bit)
+	    {
+	      (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize],
+				   num, numsize, target_bit - is_bit);
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+	    }
+	  else
+	    {
+	      mp_limb_t cy;
+	      assert (numsize < RETURN_LIMB_SIZE);
+
+	      cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize],
+				 num, numsize, is_bit - target_bit);
+	      retval[RETURN_LIMB_SIZE - numsize - 1] = cy;
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1);
+	    }
+
+	  return round_and_return (retval, bits - 1, negative, 0, 0, 0);
+	  /* NOTREACHED */
+	}
+
+      /* Store the bits we already have.  */
+      memcpy (retval, num, numsize * sizeof (mp_limb_t));
+#if RETURN_LIMB_SIZE > 1
+      if (numsize < RETURN_LIMB_SIZE)
+        retval[numsize] = 0;
+#endif
+    }
+
+  /* We have to compute at least some of the fractional digits.  */
+  {
+    /* We construct a fraction and the result of the division gives us
+       the needed digits.  The denominator is 1.0 multiplied by the
+       exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and
+       123e-6 gives 123 / 1000000.  */
+
+    int expbit;
+    int neg_exp;
+    int more_bits;
+    mp_limb_t cy;
+    mp_limb_t *psrc = den;
+    mp_limb_t *pdest = num;
+    const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+    assert (dig_no > int_no && exponent <= 0);
+
+
+    /* For the fractional part we need not process too many digits.  One
+       decimal digits gives us log_2(10) ~ 3.32 bits.  If we now compute
+                        ceil(BITS / 3) =: N
+       digits we should have enough bits for the result.  The remaining
+       decimal digits give us the information that more bits are following.
+       This can be used while rounding.  (Two added as a safety margin.)  */
+    if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
+      {
+        dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
+        more_bits = 1;
+      }
+    else
+      more_bits = 0;
+
+    neg_exp = dig_no - int_no - exponent;
+
+    /* Construct the denominator.  */
+    densize = 0;
+    expbit = 1;
+    do
+      {
+	if ((neg_exp & expbit) != 0)
+	  {
+	    mp_limb_t cy;
+	    neg_exp ^= expbit;
+
+	    if (densize == 0)
+	      {
+		densize = ttab->arraysize - _FPIO_CONST_OFFSET;
+		memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET],
+			densize * sizeof (mp_limb_t));
+	      }
+	    else
+	      {
+		cy = __mpn_mul (pdest, &__tens[ttab->arrayoff
+					      + _FPIO_CONST_OFFSET],
+				ttab->arraysize - _FPIO_CONST_OFFSET,
+				psrc, densize);
+		densize += ttab->arraysize - _FPIO_CONST_OFFSET;
+		if (cy == 0)
+		  --densize;
+		(void) SWAP (psrc, pdest);
+	      }
+	  }
+	expbit <<= 1;
+	++ttab;
+      }
+    while (neg_exp != 0);
+
+    if (psrc == num)
+      memcpy (den, num, densize * sizeof (mp_limb_t));
+
+    /* Read the fractional digits from the string.  */
+    (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent
+#ifndef USE_WIDE_CHAR
+		       , decimal, decimal_len, thousands
+#endif
+		       );
+
+    /* We now have to shift both numbers so that the highest bit in the
+       denominator is set.  In the same process we copy the numerator to
+       a high place in the array so that the division constructs the wanted
+       digits.  This is done by a "quasi fix point" number representation.
+
+       num:   ddddddddddd . 0000000000000000000000
+              |--- m ---|
+       den:                            ddddddddddd      n >= m
+                                       |--- n ---|
+     */
+
+    count_leading_zeros (cnt, den[densize - 1]);
+
+    if (cnt > 0)
+      {
+	/* Don't call `mpn_shift' with a count of zero since the specification
+	   does not allow this.  */
+	(void) __mpn_lshift (den, den, densize, cnt);
+	cy = __mpn_lshift (num, num, numsize, cnt);
+	if (cy != 0)
+	  num[numsize++] = cy;
+      }
+
+    /* Now we are ready for the division.  But it is not necessary to
+       do a full multi-precision division because we only need a small
+       number of bits for the result.  So we do not use __mpn_divmod
+       here but instead do the division here by hand and stop whenever
+       the needed number of bits is reached.  The code itself comes
+       from the GNU MP Library by Torbj\"orn Granlund.  */
+
+    exponent = bits;
+
+    switch (densize)
+      {
+      case 1:
+	{
+	  mp_limb_t d, n, quot;
+	  int used = 0;
+
+	  n = num[0];
+	  d = den[0];
+	  assert (numsize == 1 && n < d);
+
+	  do
+	    {
+	      udiv_qrnnd (quot, n, n, 0, d);
+
+#define got_limb							      \
+	      if (bits == 0)						      \
+		{							      \
+		  register int cnt;					      \
+		  if (quot == 0)					      \
+		    cnt = BITS_PER_MP_LIMB;				      \
+		  else							      \
+		    count_leading_zeros (cnt, quot);			      \
+		  exponent -= cnt;					      \
+		  if (BITS_PER_MP_LIMB - cnt > MANT_DIG)		      \
+		    {							      \
+		      used = MANT_DIG + cnt;				      \
+		      retval[0] = quot >> (BITS_PER_MP_LIMB - used);	      \
+		      bits = MANT_DIG + 1;				      \
+		    }							      \
+		  else							      \
+		    {							      \
+		      /* Note that we only clear the second element.  */      \
+		      /* The conditional is determined at compile time.  */   \
+		      if (RETURN_LIMB_SIZE > 1)				      \
+			retval[1] = 0;					      \
+		      retval[0] = quot;					      \
+		      bits = -cnt;					      \
+		    }							      \
+		}							      \
+	      else if (bits + BITS_PER_MP_LIMB <= MANT_DIG)		      \
+		__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB,   \
+				quot);					      \
+	      else							      \
+		{							      \
+		  used = MANT_DIG - bits;				      \
+		  if (used > 0)						      \
+		    __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot);    \
+		}							      \
+	      bits += BITS_PER_MP_LIMB
+
+	      got_limb;
+	    }
+	  while (bits <= MANT_DIG);
+
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || n != 0);
+	}
+      case 2:
+	{
+	  mp_limb_t d0, d1, n0, n1;
+	  mp_limb_t quot = 0;
+	  int used = 0;
+
+	  d0 = den[0];
+	  d1 = den[1];
+
+	  if (numsize < densize)
+	    {
+	      if (num[0] >= d1)
+		{
+		  /* The numerator of the number occupies fewer bits than
+		     the denominator but the one limb is bigger than the
+		     high limb of the numerator.  */
+		  n1 = 0;
+		  n0 = num[0];
+		}
+	      else
+		{
+		  if (bits <= 0)
+		    exponent -= BITS_PER_MP_LIMB;
+		  else
+		    {
+		      if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
+			__mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+					BITS_PER_MP_LIMB, 0);
+		      else
+			{
+			  used = MANT_DIG - bits;
+			  if (used > 0)
+			    __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+			}
+		      bits += BITS_PER_MP_LIMB;
+		    }
+		  n1 = num[0];
+		  n0 = 0;
+		}
+	    }
+	  else
+	    {
+	      n1 = num[1];
+	      n0 = num[0];
+	    }
+
+	  while (bits <= MANT_DIG)
+	    {
+	      mp_limb_t r;
+
+	      if (n1 == d1)
+		{
+		  /* QUOT should be either 111..111 or 111..110.  We need
+		     special treatment of this rare case as normal division
+		     would give overflow.  */
+		  quot = ~(mp_limb_t) 0;
+
+		  r = n0 + d1;
+		  if (r < d1)	/* Carry in the addition?  */
+		    {
+		      add_ssaaaa (n1, n0, r - d0, 0, 0, d0);
+		      goto have_quot;
+		    }
+		  n1 = d0 - (d0 != 0);
+		  n0 = -d0;
+		}
+	      else
+		{
+		  udiv_qrnnd (quot, r, n1, n0, d1);
+		  umul_ppmm (n1, n0, d0, quot);
+		}
+
+	    q_test:
+	      if (n1 > r || (n1 == r && n0 > 0))
+		{
+		  /* The estimated QUOT was too large.  */
+		  --quot;
+
+		  sub_ddmmss (n1, n0, n1, n0, 0, d0);
+		  r += d1;
+		  if (r >= d1)	/* If not carry, test QUOT again.  */
+		    goto q_test;
+		}
+	      sub_ddmmss (n1, n0, r, 0, n1, n0);
+
+	    have_quot:
+	      got_limb;
+	    }
+
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || n1 != 0 || n0 != 0);
+	}
+      default:
+	{
+	  int i;
+	  mp_limb_t cy, dX, d1, n0, n1;
+	  mp_limb_t quot = 0;
+	  int used = 0;
+
+	  dX = den[densize - 1];
+	  d1 = den[densize - 2];
+
+	  /* The division does not work if the upper limb of the two-limb
+	     numerator is greater than the denominator.  */
+	  if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0)
+	    num[numsize++] = 0;
+
+	  if (numsize < densize)
+	    {
+	      mp_size_t empty = densize - numsize;
+
+	      if (bits <= 0)
+		{
+		  register int i;
+		  for (i = numsize; i > 0; --i)
+		    num[i + empty] = num[i - 1];
+		  MPN_ZERO (num, empty + 1);
+		  exponent -= empty * BITS_PER_MP_LIMB;
+		}
+	      else
+		{
+		  if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG)
+		    {
+		      /* We make a difference here because the compiler
+			 cannot optimize the `else' case that good and
+			 this reflects all currently used FLOAT types
+			 and GMP implementations.  */
+		      register int i;
+#if RETURN_LIMB_SIZE <= 2
+		      assert (empty == 1);
+		      __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+				      BITS_PER_MP_LIMB, 0);
+#else
+		      for (i = RETURN_LIMB_SIZE; i > empty; --i)
+			retval[i] = retval[i - empty];
+#endif
+		      for (i = numsize; i > 0; --i)
+			num[i + empty] = num[i - 1];
+		      MPN_ZERO (num, empty + 1);
+		    }
+		  else
+		    {
+		      used = MANT_DIG - bits;
+		      if (used >= BITS_PER_MP_LIMB)
+			{
+			  register int i;
+			  (void) __mpn_lshift (&retval[used
+						       / BITS_PER_MP_LIMB],
+					       retval, RETURN_LIMB_SIZE,
+					       used % BITS_PER_MP_LIMB);
+			  for (i = used / BITS_PER_MP_LIMB; i >= 0; --i)
+			    retval[i] = 0;
+			}
+		      else if (used > 0)
+			__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+		    }
+		  bits += empty * BITS_PER_MP_LIMB;
+		}
+	    }
+	  else
+	    {
+	      int i;
+	      assert (numsize == densize);
+	      for (i = numsize; i > 0; --i)
+		num[i] = num[i - 1];
+	    }
+
+	  den[densize] = 0;
+	  n0 = num[densize];
+
+	  while (bits <= MANT_DIG)
+	    {
+	      if (n0 == dX)
+		/* This might over-estimate QUOT, but it's probably not
+		   worth the extra code here to find out.  */
+		quot = ~(mp_limb_t) 0;
+	      else
+		{
+		  mp_limb_t r;
+
+		  udiv_qrnnd (quot, r, n0, num[densize - 1], dX);
+		  umul_ppmm (n1, n0, d1, quot);
+
+		  while (n1 > r || (n1 == r && n0 > num[densize - 2]))
+		    {
+		      --quot;
+		      r += dX;
+		      if (r < dX) /* I.e. "carry in previous addition?" */
+			break;
+		      n1 -= n0 < d1;
+		      n0 -= d1;
+		    }
+		}
+
+	      /* Possible optimization: We already have (q * n0) and (1 * n1)
+		 after the calculation of QUOT.  Taking advantage of this, we
+		 could make this loop make two iterations less.  */
+
+	      cy = __mpn_submul_1 (num, den, densize + 1, quot);
+
+	      if (num[densize] != cy)
+		{
+		  cy = __mpn_add_n (num, num, den, densize);
+		  assert (cy != 0);
+		  --quot;
+		}
+	      n0 = num[densize] = num[densize - 1];
+	      for (i = densize - 1; i > 0; --i)
+		num[i] = num[i - 1];
+
+	      got_limb;
+	    }
+
+	  for (i = densize; num[i] == 0 && i >= 0; --i)
+	    ;
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || i >= 0);
+	}
+      }
+  }
+
+  /* NOTREACHED */
+}
+#if defined _LIBC && !defined USE_WIDE_CHAR
+libc_hidden_def (INTERNAL (__STRTOF))
+#endif
+
+/* External user entry point.  */
 
-weak_alias (__strtod_l, strtod_l)
+FLOAT
+#ifdef weak_function
+weak_function
+#endif
+__STRTOF (nptr, endptr, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     __locale_t loc;
+{
+  return INTERNAL (__STRTOF) (nptr, endptr, 0, loc);
+}
+weak_alias (__STRTOF, STRTOF)
diff --git a/stdlib/strtof.c b/stdlib/strtof.c
index 9d070279f8..b98cb9bfde 100644
--- a/stdlib/strtof.c
+++ b/stdlib/strtof.c
@@ -1,22 +1,35 @@
+/* Read decimal floating point numbers.
+   This file is part of the GNU C Library.
+   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
 /* The actual implementation for all floating point sizes is in strtod.c.
    These macros tell it to produce the `float' version, `strtof'.  */
 
 #define	FLOAT		float
 #define	FLT		FLT
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# define STRTOF		__strtof_l
+#ifdef USE_WIDE_CHAR
+#define STRTOF		wcstof
+#define STRTOF_L	__wcstof_l
 #else
 # define STRTOF		strtof
+# define STRTOF_L	__strtof_l
 #endif
-#define	MPN2FLOAT	__mpn_construct_float
-#define	FLOAT_HUGE_VAL	HUGE_VALF
-#define SET_MANTISSA(flt, mant) \
-  do { union ieee754_float u;						      \
-       u.f = (flt);							      \
-       if ((mant & 0x7fffff) == 0)					      \
-	 mant = 0x400000;						      \
-       u.ieee.mantissa = (mant) & 0x7fffff;				      \
-       (flt) = u.f;							      \
-  } while (0)
+
 
 #include "strtod.c"
diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c
index 1187ffc73b..bbc7611e1e 100644
--- a/stdlib/strtof_l.c
+++ b/stdlib/strtof_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to float value, using given locale.
-   Copyright (C) 1997,98,2002 Free Software Foundation, Inc.
+   Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,14 +18,30 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
-
 #include <xlocale.h>
 
 extern float ____strtof_l_internal (const char *, char **, int, __locale_t);
 extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 						       int, int, __locale_t);
 
-#include <strtof.c>
-
-weak_alias (__strtof_l, strtof_l)
+#define	FLOAT		float
+#define	FLT		FLT
+#ifdef USE_WIDE_CHAR
+# define STRTOF		wcstof_l
+# define __STRTOF	__wcstof_l
+#else
+# define STRTOF		strtof_l
+# define __STRTOF	__strtof_l
+#endif
+#define	MPN2FLOAT	__mpn_construct_float
+#define	FLOAT_HUGE_VAL	HUGE_VALF
+#define SET_MANTISSA(flt, mant) \
+  do { union ieee754_float u;						      \
+       u.f = (flt);							      \
+       if ((mant & 0x7fffff) == 0)					      \
+	 mant = 0x400000;						      \
+       u.ieee.mantissa = (mant) & 0x7fffff;				      \
+       (flt) = u.f;							      \
+  } while (0)
+
+#include "strtod_l.c"
diff --git a/stdlib/strtold.c b/stdlib/strtold.c
new file mode 100644
index 0000000000..0bb227a84f
--- /dev/null
+++ b/stdlib/strtold.c
@@ -0,0 +1,35 @@
+/* Read decimal floating point numbers.
+   This file is part of the GNU C Library.
+   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* The actual implementation for all floating point sizes is in strtod.c.
+   These macros tell it to produce the `float' version, `strtof'.  */
+
+#define	FLOAT		long double
+#define	FLT		LDBL
+#ifdef USE_WIDE_CHAR
+# define STRTOF		wcstold
+# define STRTOF_L	__wcstold_l
+#else
+# define STRTOF		strtold
+# define STRTOF_L	__strtold_l
+#endif
+
+
+#include "strtod.c"
diff --git a/stdlib/strtold_l.c b/stdlib/strtold_l.c
deleted file mode 100644
index c3a4e79390..0000000000
--- a/stdlib/strtold_l.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Convert string representing a number to float value, using given locale.
-   Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <math.h>
-#include <xlocale.h>
-
-#ifndef __NO_LONG_DOUBLE_MATH
-
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
-
-extern long double ____strtold_l_internal (const char *, char **, int,
-					   __locale_t);
-extern unsigned long long int ____strtoull_l_internal (const char *, char **,
-						       int, int, __locale_t);
-
-# include <strtold.c>
-
-#else
-/* There is no `long double' type, use the `double' implementations.  */
-extern double ____strtod_l_internal (const char *, char **, int,
-				     __locale_t);
-long double
-____strtold_l_internal (const char *nptr, char **endptr, int group,
-			__locale_t loc)
-{
-  return ____strtod_l_internal (nptr, endptr, group, loc);
-}
-
-long double
-__strtold_l (const char *nptr, char **endptr, __locale_t loc)
-{
-  return ____strtod_l_internal (nptr, endptr, 0, loc);
-}
-#endif
-
-weak_alias (__strtold_l, strtold_l)