cvs.gedasymbols.org/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2008/04/10/17:34:03

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
X-Authenticated: #27081556
X-Provags-ID: V01U2FsdGVkX1/FDgxEV6bFroPYVihZTfiX5T5WTDShXrZBdJvIoJ
UV1mfHWfsjgBOe
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
To: djgpp-workers AT delorie DOT com
Subject: Re: Hex float string conversion for strto[dfld]
Date: Thu, 10 Apr 2008 23:30:39 +0200
User-Agent: KMail/1.9.5
References: <200804082232 DOT 28045 DOT juan DOT guerrero AT gmx DOT de> <200804082050 DOT m38KoI1P003051 AT envy DOT delorie DOT com>
In-Reply-To: <200804082050.m38KoI1P003051@envy.delorie.com>
MIME-Version: 1.0
Message-Id: <200804102330.40487.juan.guerrero@gmx.de>
X-Y-GMX-Trusted: 0
Reply-To: djgpp-workers AT delorie DOT com

Am Dienstag, 8. April 2008 22:50 schrieben Sie:
> 
> Please add suitable tests to the test for these, and if it all passes,
> it's OK.

I have written a small test program to test a new version of strtold.
This is  the output it produces:

Integers.
test string: <0x1 ###>	endp: < ###>	value: 1.000000e+00
test string: <0x2 ###>	endp: < ###>	value: 2.000000e+00
test string: <0xF ###>	endp: < ###>	value: 1.500000e+01
test string: <0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef ###>	endp: < ###>	value: 5.146315e+74
Zeros
test string: <0x0 ###>	endp: < ###>	value: 0.000000e+00
test string: <0x0. ###>	endp: < ###>	value: 0.000000e+00
test string: <0x.0 ###>	endp: < ###>	value: 0.000000e+00
test string: <0x000.000 ###>	endp: < ###>	value: 0.000000e+00
test string: <0x0.0P-00###>	endp: <###>	value: 0.000000e+00
test string: <0x0.0P+00###>	endp: <###>	value: 0.000000e+00
test string: <0x0.P-00###>	endp: <###>	value: 0.000000e+00
test string: <0x.0P-00###>	endp: <###>	value: 0.000000e+00
Floating points.
test string: <0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+123###>	endp: <###>	value: 1.533599e-33
test string: <0x0.0P+9999999999999999###>	endp: <###>	value: 0.000000e+00
test string: <0x1. ###>	endp: < ###>	value: 1.000000e+00
test string: <0x1.P00###>	endp: <###>	value: 1.000000e+00
test string: <0x1P+0###>	endp: <###>	value: 1.000000e+00
test string: <0x.1P-0###>	endp: <###>	value: 6.250000e-02
test string: <0x12345678.9ABCDEF1p+12345 ###>	endp: < ###>	value: 5.014109e+3724
test string: <0xF.EDcba ###>	endp: < ###>	value: 1.592889e+01
test string: <0x123456789abcdef.fedcba987654321 ###>	endp: < ###>	value: 8.198553e+16
Overflow and underflow errors.
test string: <0x1.0P+9999999999999999###>	endp: <###>	value: Inf  ERANGE
test string: <0x7.8P+123456789###>	endp: <###>	value: Inf  ERANGE
test string: <0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+987654321###>	endp: <###>	value: Inf  ERANGE
test string: <0x1.0P-9999999999999999###>	endp: <###>	value: 0.000000e+00  ERANGE
test string: <0x7.8P-123456789###>	endp: <###>	value: 0.000000e+00  ERANGE
test string: <0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P-987654321###>	endp: <###>	value: 0.000000e+00  ERANGE
Parsing errors.
test string: <0x 123 ###>	endp: < 123 ###>	value: 0.000000e+00  EINVAL
test string: <0x123. 123 ###>	endp: < 123 ###>	value: 2.910000e+02
test string: <0x123.123 p123 ###>	endp: < p123 ###>	value: 2.910710e+02
test string: <0x123.123p 123 ###>	endp: <p 123 ###>	value: 2.910710e+02

If I have missed some test case, please let me know.  There are 3 versions of
the program with different value ranges to test strto[dfld].  Because my linux
does not support hex floating strings I have checked against the strtod version
from gnulib.  Of course the test programs shall only test the new features.

Regards,
Juan M. Guerrero


2008-04-10  Juan Manuel Guerrero  <juan DOT guerrero AT gmx DOT de>
	Diffs against djgpp CVS head of 2008-04-08.


	* src/libc/ansi/stdlib/strtold.c: Conversion of hex floating point
	strings of the form 0xH.HHH[P|p][+|-]DDD implemented.

	* src/libc/ansi/stdlib/strtold.txh: Info about hex floating point
	string conversion added.

	* src/libc/ansi/stdlib/strtod.c: Conversion of hex floating point
	strings of the form 0xH.HHH[P|p][+|-]DDD implemented.

	* src/libc/ansi/stdlib/strtod.txh: Info about hex floating point
	string conversion added.

	* src/libc/c99/stdlib/strtof.c: Conversion of hex floating point
	strings of the form 0xH.HHH[P|p][+|-]DDD implemented.

	* src/libc/c99/stdlib/strtof.txh: Info about hex floating point
	string conversion added.

	*tests/libc/ansi/stdlib/makefile: strtold.c added to the target list.

	*tests/libc/ansi/stdlib/strtod.c: Test cases for hex float string
	conversion added.

	*tests/libc/ansi/stdlib/strtold.c: Initial release.

	*tests/libc/c99/stdlib/makefile: strtof.c added to the target list.

	*tests/libc/c99/stdlib/strtof.c: Initial release.




diff -aprNU3 djgpp.orig/src/libc/ansi/stdlib/strtod.c djgpp/src/libc/ansi/stdlib/strtod.c
--- djgpp.orig/src/libc/ansi/stdlib/strtod.c	2008-04-08 17:55:48 +0000
+++ djgpp/src/libc/ansi/stdlib/strtod.c	2008-04-10 21:22:46 +0000
@@ -15,6 +15,18 @@
 #include <libc/unconst.h>
 #include <libc/ieee.h>
 
+#define HEX_DIGIT_SIZE    (4)
+#define DOUBLE_BIAS       (0x3FFU)
+#define MAX_BIN_EXPONENT  (1023)   /*  Max. and min. binary exponent (inclusive) as  */
+#define MIN_BIN_EXPONENT  (-1022)  /*  defined in Intel manual (253665.pdf, Table 4.2).  */
+#define IS_DEC_DIGIT(x)   (((x) >= '0') && ((x) <= '9'))
+#define IS_HEX_DIGIT(x)   ((((x) >= 'A') && ((x) <= 'F')) || \
+                           (((x) >= 'a') && ((x) <= 'f')) || \
+                           IS_DEC_DIGIT(x))
+#define IS_EXPONENT(x)    (((x[0]) == 'P' || (x[0]) == 'p') && \
+                           (x[1] == '+' || x[1] == '-' || IS_DEC_DIGIT(x[1])))
+
+
 double
 strtod(const char *s, char **sret)
 {
@@ -113,8 +125,170 @@ strtod(const char *s, char **sret)
     return (t.d);
   }
 
+  /* Handle 0xH.HHH[p|P][+|-]DDD. */
+  if ( ! strnicmp( "0x", s, 2 ) )
+  {
+    int digits, integer_digits;
+    long int bin_exponent;
+    unsigned long long int mantissa;
+    _double_union_t d_value;
+
+
+    /*
+     *  Mantissa.
+     *  13 hex digits fit into the fraction part.
+     */
+    bin_exponent = 0;
+    integer_digits = 0;
+    mantissa = 0x00ULL;
+    s += 2;
+    while (integer_digits < 16 && IS_HEX_DIGIT(*s))
+    {
+      flags = 1;
+      mantissa <<= HEX_DIGIT_SIZE;
+      mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                  ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+      if (mantissa)  /*  Discarts leading zeros.  */
+        integer_digits++;  /*  Counts hex digits.  16**integer_digits.  */
+      s++;
+    }
+    if (integer_digits)
+    {
+      /*
+       *  Compute the binary exponent for a normalized mantissa by
+       *  shifting the decimal point inside the most significant hex digit.
+       */
+      unsigned long long bit = 0x01ULL;
+
+      digits = 0;
+      if (IS_HEX_DIGIT(*s))
+      {
+        char *t = unconst(s, char *);
+
+        for (; IS_HEX_DIGIT(*t); t++)
+          digits++;  /*  Counts hex digits.  */
+      }
+      bin_exponent = integer_digits * HEX_DIGIT_SIZE - 1;  /*  2**bin_exponent.  */
+      for (bit <<= bin_exponent; !(mantissa & bit); bin_exponent--)
+        bit >>= 1;
+      bin_exponent += digits * HEX_DIGIT_SIZE;
+    }
+
+    if (*s == decimal)
+    {
+      int fraction_zeros = 0;
+
+      s++;
+      digits = integer_digits;
+      while ((digits - fraction_zeros) < 16 && IS_HEX_DIGIT(*s))
+      {
+        flags = 1;
+        digits++;  /*  Counts hex digits.  */
+        mantissa <<= HEX_DIGIT_SIZE;
+        mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                    ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+        if (mantissa == 0)
+          fraction_zeros++;  /*  Counts hex zeros.  16**(-fraction_zeros + 1).  */
+        s++;
+      }
+      if (!integer_digits && mantissa)
+      {
+        /*
+         *  Compute the binary exponent for a normalized mantissa by
+         *  shifting the decimal point inside the most significant hex digit.
+         */
+        unsigned long long bit = 0x01ULL;
+
+        bin_exponent = -fraction_zeros * HEX_DIGIT_SIZE;  /*  2**bin_exponent.  */
+        for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--)
+          bit >>= 1;
+      }
+    }
+
+    if (!flags)
+    {
+      if (sret)
+        *sret = unconst(s, char *);
+      errno = EINVAL;  /*  No valid mantissa, no convertion could be performed.  */
+      return 0.0L;
+    }
+
+    if (mantissa)
+    {
+      /*
+       *  Normalize mantissa.
+       */
+      while (!(mantissa & 0x8000000000000000ULL))
+        mantissa <<= 1;  /*  Shift a binary 1 into the integer part of the mantissa.  */
+      mantissa >>= (63 - 52);
+      /*  At this point the mantissa is normalized and the exponent has been adjusted accordingly.  */
+    }
+
+
+    /*
+     *  After discarting all hex digits left,
+     *  if the next character is P or p
+     *  continue with the extraction of the
+     *  exponent, else any other character
+     *  that have appeared terminates the number.
+     */
+    while (IS_HEX_DIGIT(*s))
+      s++;
+
+    /*
+     *  Exponent.
+     */
+    if (IS_EXPONENT(s))
+    {
+      long int exponent = 0.0;
+      s++;
+      if (*s == '+')
+        s++;
+      else if (*s == '-')
+      {
+        esign = -1;
+        s++;
+      }
+
+      while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s))
+      {
+        exponent *= 10;
+        exponent += *s - '0';
+        s++;
+      }
+      bin_exponent += esign * exponent;  /*  2**bin_exponent.  */
+      while (IS_DEC_DIGIT(*s))
+        s++;  /*  Discart rest of exponent.  */
+    }
+
+
+    if (sret)
+      *sret = unconst(s, char *);
+    if (mantissa)
+    {
+      if (bin_exponent > MAX_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return sign * HUGE_VAL;
+      }
+      else if(bin_exponent < MIN_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return 0.0;
+      }
+      d_value.dt.sign      = (sign == 1) ? 0 : 1;
+      d_value.dt.exponent  = 0x7FFFU & (bin_exponent + DOUBLE_BIAS);
+      d_value.dt.mantissah = 0x000FFFFFUL & (mantissa >> 32);
+      d_value.dt.mantissal = 0xFFFFFFFFUL & mantissa;
+    }
+    else
+      d_value.d = sign * 0.0;
+
+    return d_value.d;
+  }
+
   /* Handle ordinary numbers. */
-  while ((*s >= '0') && (*s <= '9'))
+  while (IS_DEC_DIGIT(*s))
   {
     flags |= 1;
     r *= 10.0;
@@ -151,7 +325,7 @@ strtod(const char *s, char **sret)
       s++;
       esign = -1;
     }
-    while ((*s >= '0') && (*s <= '9'))
+    while (IS_DEC_DIGIT(*s))
     {
       e *= 10;
       e += *s - '0';
diff -aprNU3 djgpp.orig/src/libc/ansi/stdlib/strtod.txh djgpp/src/libc/ansi/stdlib/strtod.txh
--- djgpp.orig/src/libc/ansi/stdlib/strtod.txh	2003-10-25 11:15:58 +0000
+++ djgpp/src/libc/ansi/stdlib/strtod.txh	2008-04-10 22:31:50 +0000
@@ -5,19 +5,19 @@
 @example
 #include <stdlib.h>
 
-double strtod(const char *s, char **endp);
+double strtod(const char *@var{s}, char **@var{endp});
 @end example
 
 @subheading Description
 
-This function converts as many characters of @var{s} as look like a
-floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
-``NaN(@var{optional decimal-number})'',
-``NaN(@var{optional octal-number})''
-and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
-pointer, a pointer to the first unconverted character will be stored
-in the location pointed to by @var{endp}.
+This function converts as many characters of @var{s} that look like a
+floating point number into that number.  The floating point number may
+also take the form of a hex floating point number (case-insensitively)
+like this [+|-]0xH.HHHp[+|-]DDD.  It also recognises (case-insensitively)
+``Inf'', ``Infinity'', ``NaN'', ``NaN(@var{optional decimal-number})'',
+``NaN(@var{optional octal-number})'' and ``NaN(@var{optional hex-number})''.
+If @var{endp} is not a null pointer, a pointer to the first unconverted
+character will be stored in the location pointed to by @var{endp}.  
 
 @subheading Return Value
 
@@ -66,6 +66,7 @@ char buf[] = "123ret";
 char buf2[] = "0x123ret";
 char buf3[] = "NAN(123)";
 char buf4[] = "NAN(0x123)";
+char buf5[] = "0x1234567.89ABCDefP+123 foobar";
 char *bp;
 double x, x2, x3, x4;
 
@@ -73,5 +74,6 @@ x = strtod(buf, &bp);
 x2 = strtod(buf2, &bp);
 x3 = strtod(buf3, &bp);
 x4 = strtod(buf4, &bp);
+x5 = strtod(buf5, &bp);
 @end example
 
diff -aprNU3 djgpp.orig/src/libc/ansi/stdlib/strtold.c djgpp/src/libc/ansi/stdlib/strtold.c
--- djgpp.orig/src/libc/ansi/stdlib/strtold.c	2003-11-08 12:19:40 +0000
+++ djgpp/src/libc/ansi/stdlib/strtold.c	2008-04-10 21:24:16 +0000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
@@ -6,11 +7,23 @@
 #include <locale.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <errno.h>
 #include <math.h>
 #include <string.h>
 #include <libc/unconst.h>
 #include <libc/ieee.h>
 
+#define HEX_DIGIT_SIZE    (4)
+#define LONG_DOUBLE_BIAS  (0x3FFFU)
+#define MAX_BIN_EXPONENT  (16383)   /*  Max. and min. binary exponent (inclusive) as  */
+#define MIN_BIN_EXPONENT  (-16382)  /*  defined in Intel manual (253665.pdf, Table 4.2).  */
+#define IS_DEC_DIGIT(x)   (((x) >= '0') && ((x) <= '9'))
+#define IS_HEX_DIGIT(x)   ((((x) >= 'A') && ((x) <= 'F')) || \
+                           (((x) >= 'a') && ((x) <= 'f')) || \
+                           IS_DEC_DIGIT(x))
+#define IS_EXPONENT(x)    (((x[0]) == 'P' || (x[0]) == 'p') && \
+                           (x[1] == '+' || x[1] == '-' || IS_DEC_DIGIT(x[1])))
+
 static long double powten[] =
 {
   1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
@@ -116,8 +129,193 @@ strtold(const char *s, char **sret)
     return (t.ld);
   }
 
+  /* Handle 0xH.HHH[p|P][+|-]DDD. */
+  if ( ! strnicmp( "0x", s, 2 ) )
+  {
+    int digits, integer_digits;
+    long long int bin_exponent;
+    unsigned long long int mantissa;
+    _longdouble_union_t ld_value;
+
+
+    /*
+     *  Mantissa.
+     *  16 hex digits fit into the mantissa
+     *  including the explicit integer bit.
+     */
+    bin_exponent = 0;
+    integer_digits = 0;
+    mantissa = 0x00ULL;
+    s += 2;
+    while (integer_digits < 16 && IS_HEX_DIGIT(*s))
+    {
+      flags = 1;
+      mantissa <<= HEX_DIGIT_SIZE;
+      mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                  ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+      if (mantissa)  /*  Discarts leading zeros.  */
+        integer_digits++;  /*  Counts hex digits.  16**integer_digits.  */
+      s++;
+    }
+    if (integer_digits)
+    {
+      /*
+       *  Compute the binary exponent for a normalized mantissa by
+       *  shifting the decimal point inside the most significant hex digit.
+       */
+      unsigned long long bit = 0x01ULL;
+
+      digits = 0;
+      if (IS_HEX_DIGIT(*s))
+      {
+        char *t = unconst(s, char *);
+
+        for (; IS_HEX_DIGIT(*t); t++)
+          digits++;  /*  Counts hex digits.  */
+      }
+      bin_exponent = integer_digits * HEX_DIGIT_SIZE - 1;  /*  2**bin_exponent.  */
+      for (bit <<= bin_exponent; !(mantissa & bit); bin_exponent--)
+        bit >>= 1;
+      bin_exponent += digits * HEX_DIGIT_SIZE;
+    }
+
+    if (*s == decimal)
+    {
+      int fraction_zeros = 0;
+
+      s++;
+      digits = integer_digits;
+      while ((digits - fraction_zeros) < 16 && IS_HEX_DIGIT(*s))
+      {
+        flags = 1;
+        digits++;  /*  Counts hex digits.  */
+        mantissa <<= HEX_DIGIT_SIZE;
+        mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                    ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+        if (mantissa == 0)
+          fraction_zeros++;  /*  Counts hex zeros.  16**(-fraction_zeros + 1).  */
+        s++;
+      }
+      if (!integer_digits && mantissa)
+      {
+        /*
+         *  Compute the binary exponent for a normalized mantissa by
+         *  shifting the decimal point inside the most significant hex digit.
+         */
+        unsigned long long bit = 0x01ULL;
+
+        bin_exponent = -fraction_zeros * HEX_DIGIT_SIZE;  /*  2**bin_exponent.  */
+        for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--)
+          bit >>= 1;
+      }
+    }
+
+    if (!flags)
+    {
+      if (sret)
+        *sret = unconst(s, char *);
+      errno = EINVAL;  /*  No valid mantissa, no convertion could be performed.  */
+      return 0.0L;
+    }
+
+    if (mantissa)
+    {
+      /*
+       *  Normalize mantissa.
+       *  If there is still a valid hex character in the string
+       *  its bits will be inserted in the LSB of the mantissa,
+       *  else zeros will be inserted.
+       */
+      for (digits = 0; !(mantissa & 0x8000000000000000ULL); digits++)
+        mantissa <<= 1;  /*  Shift a binary 1 into the integer part of the mantissa.  */
+      if (IS_HEX_DIGIT(*s))
+      {
+        unsigned long long bits = IS_DEC_DIGIT(*s) ? *s - '0' : 
+                                  ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+
+        switch (digits)
+        {
+        case 1:
+          mantissa |= (0x01ULL & bits >> 3);
+          s++;
+          break;
+        case 2:
+          mantissa |= (0x03ULL & bits >> 2);
+          s++;
+          break;
+        case 3:
+          mantissa |= (0x07ULL & bits >> 1);
+          s++;
+          break;
+        }
+      }
+      /*  At this point the mantissa is normalized and the exponent has been adjusted accordingly.  */
+    }
+
+
+    /*
+     *  After discarting all hex digits left,
+     *  if the next character is P or p
+     *  continue with the extracting of the
+     *  exponent, else any other character
+     *  that have appeared terminates the number.
+     */
+    while (IS_HEX_DIGIT(*s))
+      s++;
+
+    /*
+     *  Exponent.
+     */
+    if (IS_EXPONENT(s))
+    {
+      long long int exponent = 0.0L;
+      s++;
+      if (*s == '+')
+        s++;
+      else if (*s == '-')
+      {
+        esign = -1;
+        s++;
+      }
+
+      while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s))
+      {
+        exponent *= 10;
+        exponent += *s - '0';
+        s++;
+      }
+      bin_exponent += esign * exponent;  /*  2**bin_exponent.  */
+      while (IS_DEC_DIGIT(*s))
+        s++;  /*  Discart rest of exponent.  */
+    }
+
+    if (sret)
+      *sret = unconst(s, char *);
+    if (mantissa)
+    {
+      if (bin_exponent > MAX_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return sign * HUGE_VALL;
+      }
+      else if(bin_exponent < MIN_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return 0.0L;
+      }
+      ld_value.ldt.sign      = (sign == 1) ? 0 : 1;
+      ld_value.ldt.exponent  = 0x7FFFU & (bin_exponent + LONG_DOUBLE_BIAS);
+      ld_value.ldt.mantissah = 0xFFFFFFFFUL & (mantissa >> 32);
+      ld_value.ldt.mantissal = 0xFFFFFFFFUL & mantissa;
+    }
+    else
+      ld_value.ld = sign * 0.0L;
+
+    return ld_value.ld;
+  }
+
   /* Handle ordinary numbers. */
-  while ((*s >= '0') && (*s <= '9'))
+  while (IS_DEC_DIGIT(*s))
   {
     flags |= 1;
     r *= 10.0L;
@@ -128,7 +326,7 @@ strtold(const char *s, char **sret)
   if (*s == decimal)
   {
     s++;
-    while ((*s >= '0') && (*s <= '9'))
+    while (IS_DEC_DIGIT(*s))
     {
       flags |= 2;
       r *= 10.0L;
@@ -141,6 +339,7 @@ strtold(const char *s, char **sret)
   {
     if (sret)
       *sret = unconst(s, char *);
+    errno = EINVAL;  /*  No valid mantissa, no convertion could be performed.  */
     return 0.0L;
   }
 
@@ -154,7 +353,7 @@ strtold(const char *s, char **sret)
       s++;
       esign = -1;
     }
-    while ((*s >= '0') && (*s <= '9'))
+    while (IS_DEC_DIGIT(*s))
     {
       e *= 10;
       e += *s - '0';
diff -aprNU3 djgpp.orig/src/libc/ansi/stdlib/strtold.txh djgpp/src/libc/ansi/stdlib/strtold.txh
--- djgpp.orig/src/libc/ansi/stdlib/strtold.txh	2003-10-25 11:15:58 +0000
+++ djgpp/src/libc/ansi/stdlib/strtold.txh	2008-04-10 22:31:50 +0000
@@ -5,26 +5,26 @@
 @example
 #include <stdlib.h>
 
-long double _strtold(const char *s, char **endp);
+long double _strtold(const char *@var{s}, char **@var{endp});
 @end example
 
 @subheading Description
 
 This function converts as many characters of @var{s} that look like a
-floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
-``NaN(@var{optional decimal-number})'',
-``NaN(@var{optional octal-number})''
-and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
-pointer, a pointer to the first unconverted character will be stored
-in the location pointed to by @var{endp}.  
+floating point number into that number.  The floating point number may
+also take the form of a hex floating point number (case-insensitively)
+like this [+|-]0xH.HHHp[+|-]DDD.  It also recognises (case-insensitively)
+``Inf'', ``Infinity'', ``NaN'', ``NaN(@var{optional decimal-number})'',
+``NaN(@var{optional octal-number})'' and ``NaN(@var{optional hex-number})''.
+If @var{endp} is not a null pointer, a pointer to the first unconverted
+character will be stored in the location pointed to by @var{endp}.  
 
 There is also a standardised version of this function:
 @code{strtold} (@pxref{strtold}).
 
 @subheading Return Value
 
-The value representedby @var{s}. 
+The value represented by @var{s}. 
 
 If @var{s} is ``Inf'' or ``Infinity'', with any variations of case and
 optionally prefixed with ``+'' or ``-'', the return value is
@@ -63,6 +63,7 @@ char buf[] = "123ret";
 char buf2[] = "0x123ret";
 char buf3[] = "NAN(123)";
 char buf4[] = "NAN(0x123)";
+char buf5[] = "0x1234567.89ABCDefP+1234 foobar";
 char *bp;
 long double x, x2, x3, x4;
 
@@ -70,6 +71,7 @@ x = _strtold(buf, &bp);
 x2 = _strtold(buf2, &bp);
 x3 = _strtold(buf3, &bp);
 x4 = _strtold(buf4, &bp);
+x5 = _strtold(buf5, &bp);
 @end example
 
 @node strtold, string
@@ -79,19 +81,19 @@ x4 = _strtold(buf4, &bp);
 @example
 #include <stdlib.h>
 
-long double strtold(const char *s, char **endp);
+long double strtold(const char *@var{s}, char **@var{endp});
 @end example
 
 @subheading Description
 
 This function converts as many characters of @var{s} that look like a
-floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
-``NaN(@var{optional decimal-number}),
-``NaN(@var{optional octal-number})
-and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
-pointer, a pointer to the first unconverted character will be stored
-in the location pointed to by @var{endp}.  
+floating point number into that number.  The floating point number may
+also take the form of a hex floating point number (case-insensitively)
+like this [+|-]0xH.HHHp[+|-]DDD.  It also recognises (case-insensitively)
+``Inf'', ``Infinity'', ``NaN'', ``NaN(@var{optional decimal-number})'',
+``NaN(@var{optional octal-number})'' and ``NaN(@var{optional hex-number})''.
+If @var{endp} is not a null pointer, a pointer to the first unconverted
+character will be stored in the location pointed to by @var{endp}.  
 
 @subheading Return Value
 
@@ -137,6 +139,7 @@ char buf[] = "123ret";
 char buf2[] = "0x123ret";
 char buf3[] = "NAN(123)";
 char buf4[] = "NAN(0x123)";
+char buf5[] = "0x1234567.89abcdefP+1234 foobar";
 char *bp;
 long double x, x2, x3, x4;
 
@@ -144,4 +147,5 @@ x = strtold(buf, &bp);
 x2 = strtold(buf2, &bp);
 x3 = strtold(buf3, &bp);
 x4 = strtold(buf4, &bp);
+x5 = strtold(buf5, &bp);
 @end example
diff -aprNU3 djgpp.orig/src/libc/c99/stdlib/strtof.c djgpp/src/libc/c99/stdlib/strtof.c
--- djgpp.orig/src/libc/c99/stdlib/strtof.c	2008-04-08 18:50:30 +0000
+++ djgpp/src/libc/c99/stdlib/strtof.c	2008-04-10 21:25:22 +0000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
@@ -16,6 +17,18 @@
 #include <libc/unconst.h>
 #include <libc/ieee.h>
 
+#define HEX_DIGIT_SIZE    (4)
+#define FLOAT_BIAS        (0x7FU)
+#define MAX_BIN_EXPONENT  (127)   /*  Max. and min. binary exponent (inclusive) as  */
+#define MIN_BIN_EXPONENT  (-126)  /*  defined in Intel manual (253665.pdf, Table 4.2).  */
+#define IS_DEC_DIGIT(x)   (((x) >= '0') && ((x) <= '9'))
+#define IS_HEX_DIGIT(x)   ((((x) >= 'A') && ((x) <= 'F')) || \
+                           (((x) >= 'a') && ((x) <= 'f')) || \
+                           IS_DEC_DIGIT(x))
+#define IS_EXPONENT(x)    (((x[0]) == 'P' || (x[0]) == 'p') && \
+                           (x[1] == '+' || x[1] == '-' || IS_DEC_DIGIT(x[1])))
+
+
 float
 strtof(const char *s, char **sret)
 {
@@ -113,8 +126,170 @@ strtof(const char *s, char **sret)
     return (t.f);
   }
 
+  /* Handle 0xH.HHH[p|P][+|-]DDD. */
+  if ( ! strnicmp( "0x", s, 2 ) )
+  {
+    int digits, integer_digits;
+    int bin_exponent;
+    unsigned long int mantissa;
+    _float_union_t f_value;
+
+
+    /*
+     *  Mantissa.
+     *  6 hex digits fit into the mantissa
+     *  including the implicit integer bit.
+     */
+    bin_exponent = 0;
+    integer_digits = 0;
+    mantissa = 0x00U;
+    s += 2;
+    while (integer_digits < 8 && IS_HEX_DIGIT(*s))
+    {
+      flags = 1;
+      mantissa <<= HEX_DIGIT_SIZE;
+      mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                  ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+      if (mantissa)  /*  Discarts leading zeros.  */
+        integer_digits++;  /*  Counts hex digits.  16**integer_digits.  */
+      s++;
+    }
+    if (integer_digits)
+    {
+      /*
+       *  Compute the binary exponent for a normalized mantissa by
+       *  shifting the decimal point inside the most significant hex digit.
+       */
+      unsigned long long bit = 0x01ULL;
+
+      digits = 0;
+      if (IS_HEX_DIGIT(*s))
+      {
+        char *t = unconst(s, char *);
+
+        for (; IS_HEX_DIGIT(*t); t++)
+          digits++;  /*  Counts hex digits.  */
+      }
+      bin_exponent = integer_digits * HEX_DIGIT_SIZE - 1;  /*  2**bin_exponent.  */
+      for (bit <<= bin_exponent; !(mantissa & bit); bin_exponent--)
+        bit >>= 1;
+      bin_exponent += digits * HEX_DIGIT_SIZE;
+    }
+
+    if (*s == decimal)
+    {
+      int fraction_zeros = 0;
+
+      s++;
+      digits = integer_digits;
+      while ((digits - fraction_zeros) < 16 && IS_HEX_DIGIT(*s))
+      {
+        flags = 1;
+        digits++;  /*  Counts hex digits.  */
+        mantissa <<= HEX_DIGIT_SIZE;
+        mantissa += IS_DEC_DIGIT(*s) ? *s - '0' : 
+                    ((*s >= 'A') && (*s <= 'F')) ? *s - 'A' + 10 : *s - 'a' + 10;
+        if (mantissa == 0)
+          fraction_zeros++;  /*  Counts hex zeros.  16**(-fraction_zeros + 1).  */
+        s++;
+      }
+      if (!integer_digits && mantissa)
+      {
+        /*
+         *  Compute the binary exponent for a normalized mantissa by
+         *  shifting the decimal point inside the most significant hex digit.
+         */
+        unsigned long long bit = 0x01ULL;
+
+        bin_exponent = -fraction_zeros * HEX_DIGIT_SIZE;  /*  2**bin_exponent.  */
+        for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--)
+          bit >>= 1;
+      }
+    }
+
+    if (!flags)
+    {
+      if (sret)
+        *sret = unconst(s, char *);
+      errno = EINVAL;  /*  No valid mantissa, no convertion could be performed.  */
+      return 0.0;
+    }
+
+    if (mantissa)
+    {
+      /*
+       *  Normalize mantissa.
+       */
+      while (!(mantissa & 0x80000000ULL))
+        mantissa <<= 1;  /*  Shift a binary 1 into the integer part of the mantissa.  */
+      mantissa >>= (31 - 23);
+      /*  At this point the mantissa is normalized and the exponent has been adjusted accordingly.  */
+    }
+
+
+    /*
+     *  After discarting all hex digits left,
+     *  if the next character is P or p
+     *  continue with the extracting of the
+     *  exponent, else any other character
+     *  that have appeared terminates the number.
+     */
+    while (IS_HEX_DIGIT(*s))
+      s++;
+
+    /*
+     *  Exponent.
+     */
+    if (IS_EXPONENT(s))
+    {
+      int exponent = 0.0;
+      s++;
+      if (*s == '+')
+        s++;
+      else if (*s == '-')
+      {
+        esign = -1;
+        s++;
+      }
+
+      while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s))
+      {
+        exponent *= 10;
+        exponent += *s - '0';
+        s++;
+      }
+      bin_exponent += esign * exponent;  /*  2**bin_exponent.  */
+      while (IS_DEC_DIGIT(*s))
+        s++;  /*  Discart rest of exponent.  */
+    }
+
+
+    if (sret)
+      *sret = unconst(s, char *);
+    if (mantissa)
+    {
+      if (bin_exponent > MAX_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return sign * HUGE_VALF;
+      }
+      else if(bin_exponent < MIN_BIN_EXPONENT)
+      {
+        errno = ERANGE;
+        return 0.0;
+      }
+      f_value.ft.sign     = (sign == 1) ? 0 : 1;
+      f_value.ft.exponent = 0x07FFU & (bin_exponent + FLOAT_BIAS);
+      f_value.ft.mantissa = 0x007FFFFFU & mantissa;
+    }
+    else
+      f_value.f = sign * 0.0;
+
+    return f_value.f;
+  }
+
   /* Handle ordinary numbers. */
-  while ((*s >= '0') && (*s <= '9'))
+  while (IS_DEC_DIGIT(*s))
   {
     flags |= 1;
     r *= 10.0;
@@ -151,7 +326,7 @@ strtof(const char *s, char **sret)
       s++;
       esign = -1;
     }
-    while ((*s >= '0') && (*s <= '9'))
+    while (IS_DEC_DIGIT(*s))
     {
       e *= 10;
       e += *s - '0';
diff -aprNU3 djgpp.orig/src/libc/c99/stdlib/strtof.txh djgpp/src/libc/c99/stdlib/strtof.txh
--- djgpp.orig/src/libc/c99/stdlib/strtof.txh	2003-10-25 11:16:20 +0000
+++ djgpp/src/libc/c99/stdlib/strtof.txh	2008-04-10 22:31:50 +0000
@@ -5,19 +5,19 @@
 @example
 #include <stdlib.h>
 
-float strtof(const char *s, char **endp);
+float strtof(const char *@var{s}, char **@var{endp});
 @end example
 
 @subheading Description
 
-This function converts as many characters of @var{s} as look like a
-floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
-``NaN(@var{optional decimal-number})'',
-``NaN(@var{optional octal-number})''
-and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
-pointer, a pointer to the first unconverted character will be stored
-in the location pointed to by @var{endp}.
+This function converts as many characters of @var{s} that look like a
+floating point number into that number.  The floating point number may
+also take the form of a hex floating point number (case-insensitively)
+like this [+|-]0xH.HHHp[+|-]DDD.  It also recognises (case-insensitively)
+``Inf'', ``Infinity'', ``NaN'', ``NaN(@var{optional decimal-number})'',
+``NaN(@var{optional octal-number})'' and ``NaN(@var{optional hex-number})''.
+If @var{endp} is not a null pointer, a pointer to the first unconverted
+character will be stored in the location pointed to by @var{endp}.  
 
 @subheading Return Value
 
@@ -65,6 +65,7 @@ char buf[] = "123ret";
 char buf2[] = "0x123ret";
 char buf3[] = "NAN(123)";
 char buf4[] = "NAN(0x123)";
+char buf5[] = "0x1234567.89ABCDefP+12 foobar";
 char *bp;
 float x, x2, x3, x4;
 
@@ -72,4 +73,5 @@ x = strtof(buf, &bp);
 x2 = strtof(buf2, &bp);
 x3 = strtof(buf3, &bp);
 x4 = strtof(buf4, &bp);
+x5 = strtod(buf5, &bp);
 @end example
diff -aprNU3 djgpp.orig/tests/libc/ansi/stdlib/makefile djgpp/tests/libc/ansi/stdlib/makefile
--- djgpp.orig/tests/libc/ansi/stdlib/makefile	2005-05-11 19:59:36 +0000
+++ djgpp/tests/libc/ansi/stdlib/makefile	2008-04-10 22:41:04 +0000
@@ -4,6 +4,7 @@ SRC += env.c
 SRC += getenv.c
 SRC += mbstowcs.c
 SRC += shell.c
+SRC += strtold.c
 SRC += strtod.c
 SRC += system.c
 SRC += system2.c
diff -aprNU3 djgpp.orig/tests/libc/ansi/stdlib/strtod.c djgpp/tests/libc/ansi/stdlib/strtod.c
--- djgpp.orig/tests/libc/ansi/stdlib/strtod.c	2003-05-10 17:16:28 +0000
+++ djgpp/tests/libc/ansi/stdlib/strtod.c	2008-04-10 22:40:42 +0000
@@ -19,6 +19,48 @@ static const char *testnum[] = {
   "nan(0)",		/* nan */
   "Nan(1)",		/* nan */
   "-NaN(0xfffff)",	/* nan */
+  "-NaN(0xfffff.ffffffp+123456)",	/* nan */
+  0
+};
+
+static const char *test_string[] = {
+  /*  Integers.  */
+  "0x1 ###",
+  "0x2 ###",
+  "0xF ###",
+  "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef ###",
+  /*  Zeros.  */
+  "0x0 ###",
+  "0x0. ###",
+  "0x.0 ###",
+  "0x000.000 ###",
+  "0x0.0P-00###",
+  "0x0.0P+00###",
+  "0x0.P-00###",
+  "0x.0P-00###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+123###",
+  "0x0.0P+9999999999999999###",
+  /*  Floating points.  */
+  "0x1. ###",
+  "0x1.P00###",
+  "0x1P+0###",
+  "0x.1P-0###",
+  "0x12345678.9ABCDEF1p+345 ###",
+  "0xF.EDcba ###",
+  "0x123456789abcdef.fedcba987654321 ###",
+  /*  Overflow.  */
+  "0x1.0P+9999999999999999###",
+  "0x7.8P+123456###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+987654321###",
+  /*  Underflow.  */
+  "0x1.0P-9999999999999999###",
+  "0x7.8P-123456789###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P-987654321###",
+  /*  Errors.  */
+  "0x 123 ###",
+  "0x123. 123 ###",
+  "0x123.123 p123 ###",
+  "0x123.123p 123 ###",
   0
 };
 
@@ -38,5 +80,22 @@ int main (void)
     }
   }
 
+  for (i = 0; test_string[i]; i++)
+  {
+    errno = 0;
+    result = strtod(test_string[i], &endp);
+    switch (errno)
+    {
+    case 0:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e\n", test_string[i], endp, result);
+      break;
+    case ERANGE:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e  ERANGE\n", test_string[i], endp, result);
+      break;
+    case EINVAL:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e  EINVAL\n", test_string[i], endp, result);
+      break;
+    }
+  }
   return 0;
 }
diff -aprNU3 djgpp.orig/tests/libc/ansi/stdlib/strtold.c djgpp/tests/libc/ansi/stdlib/strtold.c
--- djgpp.orig/tests/libc/ansi/stdlib/strtold.c	1970-01-01 00:00:00 +0000
+++ djgpp/tests/libc/ansi/stdlib/strtold.c	2008-04-10 22:40:42 +0000
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static const char *testnum[] = {
+  "0e200",
+  "1e2000",
+  "0e2000000000",	/* suggested by Morten Welinder */
+  "1e6000000000",	/* overflow */
+  "1e5000",		/* ditto */
+  "1e-5000",		/* underflow */
+  "InF",		/* infinity */
+  "-inf",		/* infinity */
+  "infinity",		/* infinity */
+  "-inFinitY",		/* infinity */
+  "nAn",		/* nan */
+  "-nan",		/* nan */
+  "Nan()",		/* nan */
+  "nan(0)",		/* nan */
+  "Nan(1)",		/* nan */
+  "-NaN(0xffFFFFFfff)",	/* nan */
+  "-NaN(0xfffff.ffffffp+123456)",	/* nan */
+  0
+};
+
+static const char *test_string[] = {
+  /*  Integers.  */
+  "0x1 ###",
+  "0x2 ###",
+  "0xF ###",
+  "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef ###",
+  /*  Zeros.  */
+  "0x0 ###",
+  "0x0. ###",
+  "0x.0 ###",
+  "0x000.000 ###",
+  "0x0.0P-00###",
+  "0x0.0P+00###",
+  "0x0.P-00###",
+  "0x.0P-00###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+123###",
+  "0x0.0P+9999999999999999###",
+  /*  Floating points.  */
+  "0x1. ###",
+  "0x1.P00###",
+  "0x1P+0###",
+  "0x.1P-0###",
+  "0x12345678.9ABCDEF1p+12345 ###",
+  "0xF.EDcba ###",
+  "0x123456789abcdef.fedcba987654321 ###",
+  /*  Overflow.  */
+  "0x1.0P+9999999999999999###",
+  "0x7.8P+123456789###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+987654321###",
+  /*  Underflow.  */
+  "0x1.0P-9999999999999999###",
+  "0x7.8P-123456789###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P-987654321###",
+  /*  Errors.  */
+  "0x 123 ###",
+  "0x123. 123 ###",
+  "0x123.123 p123 ###",
+  "0x123.123p 123 ###",
+  0
+};
+
+int main(void)
+{
+  char *endp;
+  long double result;
+  int i;
+
+  for (i = 0; testnum[i]; i++)
+  {
+    printf ("%20s  ->  %-20.15g\n", testnum[i], strtold (testnum[i], (char **)0));
+    if (errno)
+    {
+      perror ("strtold");
+      errno = 0;
+    }
+  }
+
+  for (i = 0; test_string[i]; i++)
+  {
+    errno = 0;
+    result = strtold(test_string[i], &endp);
+    switch (errno)
+    {
+    case 0:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %Le\n", test_string[i], endp, result);
+      break;
+    case ERANGE:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %Le  ERANGE\n", test_string[i], endp, result);
+      break;
+    case EINVAL:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %Le  EINVAL\n", test_string[i], endp, result);
+      break;
+    }
+  }
+  return 0;
+}
+
diff -aprNU3 djgpp.orig/tests/libc/c99/stdlib/makefile djgpp/tests/libc/c99/stdlib/makefile
--- djgpp.orig/tests/libc/c99/stdlib/makefile	2003-01-08 20:18:48 +0000
+++ djgpp/tests/libc/c99/stdlib/makefile	2008-04-10 22:43:58 +0000
@@ -2,5 +2,6 @@ TOP=../..
 
 SRC += t-_exit.c
 SRC += t-strtof.c
+SRC += strtof.c
 
 include $(TOP)/../makefile.inc
diff -aprNU3 djgpp.orig/tests/libc/c99/stdlib/strtof.c djgpp/tests/libc/c99/stdlib/strtof.c
--- djgpp.orig/tests/libc/c99/stdlib/strtof.c	1970-01-01 00:00:00 +0000
+++ djgpp/tests/libc/c99/stdlib/strtof.c	2008-04-10 22:43:44 +0000
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static const char *testnum[] = {
+  "0e20",
+  "1e200",
+  "0e2000000000",	/* suggested by Morten Welinder */
+  "1e6000000000",	/* overflow */
+  "1e400",		/* ditto */
+  "1e-400",		/* underflow */
+  "InF",		/* infinity */
+  "-inf",		/* infinity */
+  "infinity",		/* infinity */
+  "-inFinitY",		/* infinity */
+  "nAn",		/* nan */
+  "-nan",		/* nan */
+  "Nan()",		/* nan */
+  "nan(0)",		/* nan */
+  "Nan(1)",		/* nan */
+  "-NaN(0xfffff)",	/* nan */
+  "-NaN(0xfffff.ffffffp+123456)",	/* nan */
+  0
+};
+
+static const char *test_string[] = {
+  /*  Integers.  */
+  "0x1 ###",
+  "0x2 ###",
+  "0xF ###",
+  "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef ###",
+  /*  Zeros.  */
+  "0x0 ###",
+  "0x0. ###",
+  "0x.0 ###",
+  "0x000.000 ###",
+  "0x0.0P-00###",
+  "0x0.0P+00###",
+  "0x0.P-00###",
+  "0x.0P-00###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+23###",
+  "0x0.0P+9999999999999999###",
+  /*  Floating points.  */
+  "0x1. ###",
+  "0x1.P00###",
+  "0x1P+0###",
+  "0x.1P-0###",
+  "0x12345678.9ABCDEF1p+34 ###",
+  "0xF.EDcba ###",
+  "0x123456789abcdef.fedcba987654321 ###",
+  /*  Overflow.  */
+  "0x1.0P+9999999999999999###",
+  "0x7.8P+1234###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P+987654321###",
+  /*  Underflow.  */
+  "0x1.0P-9999999999999999###",
+  "0x7.8P-123456###",
+  "0X00000.0000000000000000000000000000000000000000000000000000000000FED0123P-987654###",
+  /*  Errors.  */
+  "0x 123 ###",
+  "0x123. 123 ###",
+  "0x123.123 p123 ###",
+  "0x123.123p 123 ###",
+  0
+};
+
+int main (void)
+{
+  int i;
+
+  errno = 0;
+
+  for (i = 0; testnum[i]; i++)
+  {
+    printf ("%20s  ->  %-20.15g\n", testnum[i], strtof (testnum[i], (char **)0));
+    if (errno)
+    {
+      perror ("strtod");
+      errno = 0;
+    }
+  }
+
+  for (i = 0; test_string[i]; i++)
+  {
+    errno = 0;
+    result = strtof(test_string[i], &endp);
+    switch (errno)
+    {
+    case 0:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e\n", test_string[i], endp, result);
+      break;
+    case ERANGE:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e  ERANGE\n", test_string[i], endp, result);
+      break;
+    case EINVAL:
+      printf("test string: <%s>\tendp: <%s>\tvalue: %e  EINVAL\n", test_string[i], endp, result);
+      break;
+    }
+  }
+  return 0;
+} 

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019