(root)/
coreutils-9.4/
gnulib-tests/
test-strtod.c
       1  /*
       2   * Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3   * Written by Eric Blake
       4   *
       5   * This program is free software: you can redistribute it and/or modify
       6   * it under the terms of the GNU General Public License as published by
       7   * the Free Software Foundation, either version 3 of the License, or
       8   * (at your option) any later version.
       9   *
      10   * This program is distributed in the hope that it will be useful,
      11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13   * GNU General Public License for more details.
      14   *
      15   * You should have received a copy of the GNU General Public License
      16   * along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  #include <stdlib.h>
      21  
      22  #include "signature.h"
      23  SIGNATURE_CHECK (strtod, double, (char const *, char **));
      24  
      25  #include <errno.h>
      26  #include <float.h>
      27  #include <math.h>
      28  #include <string.h>
      29  
      30  #include "isnand-nolibm.h"
      31  #include "minus-zero.h"
      32  #include "macros.h"
      33  
      34  /* Avoid requiring -lm just for fabs.  */
      35  #define FABS(d) ((d) < 0.0 ? -(d) : (d))
      36  
      37  int
      38  main (void)
      39  {
      40    int status = 0;
      41    /* Subject sequence empty or invalid.  */
      42    {
      43      const char input[] = "";
      44      char *ptr;
      45      double result;
      46      errno = 0;
      47      result = strtod (input, &ptr);
      48      ASSERT (result == 0.0);
      49      ASSERT (!signbit (result));
      50      ASSERT (ptr == input);
      51      ASSERT (errno == 0 || errno == EINVAL);
      52    }
      53    {
      54      const char input[] = " ";
      55      char *ptr;
      56      double result;
      57      errno = 0;
      58      result = strtod (input, &ptr);
      59      ASSERT (result == 0.0);
      60      ASSERT (!signbit (result));
      61      ASSERT (ptr == input);
      62      ASSERT (errno == 0 || errno == EINVAL);
      63    }
      64    {
      65      const char input[] = " +";
      66      char *ptr;
      67      double result;
      68      errno = 0;
      69      result = strtod (input, &ptr);
      70      ASSERT (result == 0.0);
      71      ASSERT (!signbit (result));
      72      ASSERT (ptr == input);
      73      ASSERT (errno == 0 || errno == EINVAL);
      74    }
      75    {
      76      const char input[] = " .";
      77      char *ptr;
      78      double result;
      79      errno = 0;
      80      result = strtod (input, &ptr);
      81      ASSERT (result == 0.0);
      82      ASSERT (!signbit (result));
      83      ASSERT (ptr == input);
      84      ASSERT (errno == 0 || errno == EINVAL);
      85    }
      86    {
      87      const char input[] = " .e0";
      88      char *ptr;
      89      double result;
      90      errno = 0;
      91      result = strtod (input, &ptr);
      92      ASSERT (result == 0.0);
      93      ASSERT (!signbit (result));
      94      ASSERT (ptr == input);              /* IRIX 6.5, OSF/1 5.1 */
      95      ASSERT (errno == 0 || errno == EINVAL);
      96    }
      97    {
      98      const char input[] = " +.e-0";
      99      char *ptr;
     100      double result;
     101      errno = 0;
     102      result = strtod (input, &ptr);
     103      ASSERT (result == 0.0);
     104      ASSERT (!signbit (result));
     105      ASSERT (ptr == input);              /* IRIX 6.5, OSF/1 5.1 */
     106      ASSERT (errno == 0 || errno == EINVAL);
     107    }
     108    {
     109      const char input[] = " in";
     110      char *ptr;
     111      double result;
     112      errno = 0;
     113      result = strtod (input, &ptr);
     114      ASSERT (result == 0.0);
     115      ASSERT (!signbit (result));
     116      ASSERT (ptr == input);
     117      ASSERT (errno == 0 || errno == EINVAL);
     118    }
     119    {
     120      const char input[] = " na";
     121      char *ptr;
     122      double result;
     123      errno = 0;
     124      result = strtod (input, &ptr);
     125      ASSERT (result == 0.0);
     126      ASSERT (!signbit (result));
     127      ASSERT (ptr == input);
     128      ASSERT (errno == 0 || errno == EINVAL);
     129    }
     130  
     131    /* Simple floating point values.  */
     132    {
     133      const char input[] = "1";
     134      char *ptr;
     135      double result;
     136      errno = 0;
     137      result = strtod (input, &ptr);
     138      ASSERT (result == 1.0);
     139      ASSERT (ptr == input + 1);
     140      ASSERT (errno == 0);
     141    }
     142    {
     143      const char input[] = "1.";
     144      char *ptr;
     145      double result;
     146      errno = 0;
     147      result = strtod (input, &ptr);
     148      ASSERT (result == 1.0);
     149      ASSERT (ptr == input + 2);
     150      ASSERT (errno == 0);
     151    }
     152    {
     153      const char input[] = ".5";
     154      char *ptr;
     155      double result;
     156      errno = 0;
     157      result = strtod (input, &ptr);
     158      ASSERT (result == 0.5);
     159      ASSERT (ptr == input + 2);
     160      ASSERT (errno == 0);
     161    }
     162    {
     163      const char input[] = " 1";
     164      char *ptr;
     165      double result;
     166      errno = 0;
     167      result = strtod (input, &ptr);
     168      ASSERT (result == 1.0);
     169      ASSERT (ptr == input + 2);
     170      ASSERT (errno == 0);
     171    }
     172    {
     173      const char input[] = "+1";
     174      char *ptr;
     175      double result;
     176      errno = 0;
     177      result = strtod (input, &ptr);
     178      ASSERT (result == 1.0);
     179      ASSERT (ptr == input + 2);
     180      ASSERT (errno == 0);
     181    }
     182    {
     183      const char input[] = "-1";
     184      char *ptr;
     185      double result;
     186      errno = 0;
     187      result = strtod (input, &ptr);
     188      ASSERT (result == -1.0);
     189      ASSERT (ptr == input + 2);
     190      ASSERT (errno == 0);
     191    }
     192    {
     193      const char input[] = "1e0";
     194      char *ptr;
     195      double result;
     196      errno = 0;
     197      result = strtod (input, &ptr);
     198      ASSERT (result == 1.0);
     199      ASSERT (ptr == input + 3);
     200      ASSERT (errno == 0);
     201    }
     202    {
     203      const char input[] = "1e+0";
     204      char *ptr;
     205      double result;
     206      errno = 0;
     207      result = strtod (input, &ptr);
     208      ASSERT (result == 1.0);
     209      ASSERT (ptr == input + 4);
     210      ASSERT (errno == 0);
     211    }
     212    {
     213      const char input[] = "1e-0";
     214      char *ptr;
     215      double result;
     216      errno = 0;
     217      result = strtod (input, &ptr);
     218      ASSERT (result == 1.0);
     219      ASSERT (ptr == input + 4);
     220      ASSERT (errno == 0);
     221    }
     222    {
     223      const char input[] = "1e1";
     224      char *ptr;
     225      double result;
     226      errno = 0;
     227      result = strtod (input, &ptr);
     228      ASSERT (result == 10.0);
     229      ASSERT (ptr == input + 3);
     230      ASSERT (errno == 0);
     231    }
     232    {
     233      const char input[] = "5e-1";
     234      char *ptr;
     235      double result;
     236      errno = 0;
     237      result = strtod (input, &ptr);
     238      ASSERT (result == 0.5);
     239      ASSERT (ptr == input + 4);
     240      ASSERT (errno == 0);
     241    }
     242  
     243    /* Zero.  */
     244    {
     245      const char input[] = "0";
     246      char *ptr;
     247      double result;
     248      errno = 0;
     249      result = strtod (input, &ptr);
     250      ASSERT (result == 0.0);
     251      ASSERT (!signbit (result));
     252      ASSERT (ptr == input + 1);
     253      ASSERT (errno == 0);
     254    }
     255    {
     256      const char input[] = ".0";
     257      char *ptr;
     258      double result;
     259      errno = 0;
     260      result = strtod (input, &ptr);
     261      ASSERT (result == 0.0);
     262      ASSERT (!signbit (result));
     263      ASSERT (ptr == input + 2);
     264      ASSERT (errno == 0);
     265    }
     266    {
     267      const char input[] = "0e0";
     268      char *ptr;
     269      double result;
     270      errno = 0;
     271      result = strtod (input, &ptr);
     272      ASSERT (result == 0.0);
     273      ASSERT (!signbit (result));
     274      ASSERT (ptr == input + 3);
     275      ASSERT (errno == 0);
     276    }
     277    {
     278      const char input[] = "0e+9999999";
     279      char *ptr;
     280      double result;
     281      errno = 0;
     282      result = strtod (input, &ptr);
     283      ASSERT (result == 0.0);
     284      ASSERT (!signbit (result));
     285      ASSERT (ptr == input + 10);
     286      ASSERT (errno == 0);
     287    }
     288    {
     289      const char input[] = "0e-9999999";
     290      char *ptr;
     291      double result;
     292      errno = 0;
     293      result = strtod (input, &ptr);
     294      ASSERT (result == 0.0);
     295      ASSERT (!signbit (result));
     296      ASSERT (ptr == input + 10);
     297      ASSERT (errno == 0);
     298    }
     299    {
     300      const char input[] = "-0";
     301      char *ptr;
     302      double result;
     303      errno = 0;
     304      result = strtod (input, &ptr);
     305      ASSERT (result == 0.0);
     306      ASSERT (!!signbit (result) == !!signbit (minus_zerod)); /* IRIX 6.5, OSF/1 4.0 */
     307      ASSERT (ptr == input + 2);
     308      ASSERT (errno == 0);
     309    }
     310  
     311    /* Suffixes.  */
     312    {
     313      const char input[] = "1f";
     314      char *ptr;
     315      double result;
     316      errno = 0;
     317      result = strtod (input, &ptr);
     318      ASSERT (result == 1.0);
     319      ASSERT (ptr == input + 1);
     320      ASSERT (errno == 0);
     321    }
     322    {
     323      const char input[] = "1.f";
     324      char *ptr;
     325      double result;
     326      errno = 0;
     327      result = strtod (input, &ptr);
     328      ASSERT (result == 1.0);
     329      ASSERT (ptr == input + 2);
     330      ASSERT (errno == 0);
     331    }
     332    {
     333      const char input[] = "1e";
     334      char *ptr;
     335      double result;
     336      errno = 0;
     337      result = strtod (input, &ptr);
     338      ASSERT (result == 1.0);
     339      ASSERT (ptr == input + 1);
     340      ASSERT (errno == 0);
     341    }
     342    {
     343      const char input[] = "1e+";
     344      char *ptr;
     345      double result;
     346      errno = 0;
     347      result = strtod (input, &ptr);
     348      ASSERT (result == 1.0);
     349      ASSERT (ptr == input + 1);
     350      ASSERT (errno == 0);
     351    }
     352    {
     353      const char input[] = "1e-";
     354      char *ptr;
     355      double result;
     356      errno = 0;
     357      result = strtod (input, &ptr);
     358      ASSERT (result == 1.0);
     359      ASSERT (ptr == input + 1);
     360      ASSERT (errno == 0);
     361    }
     362    {
     363      const char input[] = "1E 2";
     364      char *ptr;
     365      double result;
     366      errno = 0;
     367      result = strtod (input, &ptr);
     368      ASSERT (result == 1.0);             /* HP-UX 11.11, IRIX 6.5, OSF/1 4.0 */
     369      ASSERT (ptr == input + 1);          /* HP-UX 11.11, IRIX 6.5 */
     370      ASSERT (errno == 0);
     371    }
     372    {
     373      const char input[] = "0x";
     374      char *ptr;
     375      double result;
     376      errno = 0;
     377      result = strtod (input, &ptr);
     378      ASSERT (result == 0.0);
     379      ASSERT (!signbit (result));
     380      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     381      ASSERT (errno == 0);
     382    }
     383    {
     384      const char input[] = "00x1";
     385      char *ptr;
     386      double result;
     387      errno = 0;
     388      result = strtod (input, &ptr);
     389      ASSERT (result == 0.0);
     390      ASSERT (!signbit (result));
     391      ASSERT (ptr == input + 2);
     392      ASSERT (errno == 0);
     393    }
     394    {
     395      const char input[] = "-0x";
     396      char *ptr;
     397      double result;
     398      errno = 0;
     399      result = strtod (input, &ptr);
     400      ASSERT (result == 0.0);
     401      ASSERT (!!signbit (result) == !!signbit (minus_zerod)); /* Mac OS X 10.3, FreeBSD 6.2, IRIX 6.5, OSF/1 4.0 */
     402      ASSERT (ptr == input + 2);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     403      ASSERT (errno == 0);
     404    }
     405    {
     406      const char input[] = "0xg";
     407      char *ptr;
     408      double result;
     409      errno = 0;
     410      result = strtod (input, &ptr);
     411      ASSERT (result == 0.0);
     412      ASSERT (!signbit (result));
     413      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     414      ASSERT (errno == 0);
     415    }
     416    {
     417      const char input[] = "0xp";
     418      char *ptr;
     419      double result;
     420      errno = 0;
     421      result = strtod (input, &ptr);
     422      ASSERT (result == 0.0);
     423      ASSERT (!signbit (result));
     424      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     425      ASSERT (errno == 0);
     426    }
     427    {
     428      const char input[] = "0XP";
     429      char *ptr;
     430      double result;
     431      errno = 0;
     432      result = strtod (input, &ptr);
     433      ASSERT (result == 0.0);
     434      ASSERT (!signbit (result));
     435      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     436      ASSERT (errno == 0);
     437    }
     438    {
     439      const char input[] = "0x.";
     440      char *ptr;
     441      double result;
     442      errno = 0;
     443      result = strtod (input, &ptr);
     444      ASSERT (result == 0.0);
     445      ASSERT (!signbit (result));
     446      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     447      ASSERT (errno == 0);
     448    }
     449    {
     450      const char input[] = "0xp+";
     451      char *ptr;
     452      double result;
     453      errno = 0;
     454      result = strtod (input, &ptr);
     455      ASSERT (result == 0.0);
     456      ASSERT (!signbit (result));
     457      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     458      ASSERT (errno == 0);
     459    }
     460    {
     461      const char input[] = "0xp+1";
     462      char *ptr;
     463      double result;
     464      errno = 0;
     465      result = strtod (input, &ptr);
     466      ASSERT (result == 0.0);
     467      ASSERT (!signbit (result));
     468      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     469      ASSERT (errno == 0);
     470    }
     471    {
     472      const char input[] = "0x.p+1";
     473      char *ptr;
     474      double result;
     475      errno = 0;
     476      result = strtod (input, &ptr);
     477      ASSERT (result == 0.0);
     478      ASSERT (!signbit (result));
     479      ASSERT (ptr == input + 1);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, AIX 7.1 */
     480      ASSERT (errno == 0);
     481    }
     482    {
     483      const char input[] = "1p+1";
     484      char *ptr;
     485      double result;
     486      errno = 0;
     487      result = strtod (input, &ptr);
     488      ASSERT (result == 1.0);
     489      ASSERT (ptr == input + 1);
     490      ASSERT (errno == 0);
     491    }
     492    {
     493      const char input[] = "1P+1";
     494      char *ptr;
     495      double result;
     496      errno = 0;
     497      result = strtod (input, &ptr);
     498      ASSERT (result == 1.0);
     499      ASSERT (ptr == input + 1);
     500      ASSERT (errno == 0);
     501    }
     502  
     503    /* Overflow/underflow.  */
     504    {
     505      const char input[] = "1E1000000";
     506      char *ptr;
     507      double result;
     508      errno = 0;
     509      result = strtod (input, &ptr);
     510      ASSERT (result == HUGE_VAL);
     511      ASSERT (ptr == input + 9);          /* OSF/1 5.1 */
     512      ASSERT (errno == ERANGE);
     513    }
     514    {
     515      const char input[] = "-1E1000000";
     516      char *ptr;
     517      double result;
     518      errno = 0;
     519      result = strtod (input, &ptr);
     520      ASSERT (result == -HUGE_VAL);
     521      ASSERT (ptr == input + 10);
     522      ASSERT (errno == ERANGE);
     523    }
     524    {
     525      const char input[] = "1E-100000";
     526      char *ptr;
     527      double result;
     528      errno = 0;
     529      result = strtod (input, &ptr);
     530      ASSERT (0.0 <= result && result <= DBL_MIN);
     531      ASSERT (!signbit (result));
     532      ASSERT (ptr == input + 9);
     533      ASSERT (errno == ERANGE);
     534    }
     535    {
     536      const char input[] = "-1E-100000";
     537      char *ptr;
     538      double result;
     539      errno = 0;
     540      result = strtod (input, &ptr);
     541      ASSERT (-DBL_MIN <= result && result <= 0.0);
     542  #if 0
     543      /* FIXME - this is glibc bug 5995; POSIX allows returning positive
     544         0 on negative underflow, even though quality of implementation
     545         demands preserving the sign.  Disable this test until fixed
     546         glibc is more prevalent.  */
     547      ASSERT (!!signbit (result) == !!signbit (minus_zerod)); /* glibc-2.3.6, mingw */
     548  #endif
     549      ASSERT (ptr == input + 10);
     550      ASSERT (errno == ERANGE);
     551    }
     552    {
     553      const char input[] = "1E 1000000";
     554      char *ptr;
     555      double result;
     556      errno = 0;
     557      result = strtod (input, &ptr);
     558      ASSERT (result == 1.0);             /* HP-UX 11.11, IRIX 6.5, OSF/1 4.0 */
     559      ASSERT (ptr == input + 1);          /* HP-UX 11.11, IRIX 6.5 */
     560      ASSERT (errno == 0);
     561    }
     562    {
     563      const char input[] = "0x1P 1000000";
     564      char *ptr;
     565      double result;
     566      errno = 0;
     567      result = strtod (input, &ptr);
     568      ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     569      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     570      ASSERT (errno == 0);
     571    }
     572  
     573    /* Infinity.  */
     574    {
     575      const char input[] = "iNf";
     576      char *ptr;
     577      double result;
     578      errno = 0;
     579      result = strtod (input, &ptr);
     580      ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     581      ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
     582      ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
     583    }
     584    {
     585      const char input[] = "-InF";
     586      char *ptr;
     587      double result;
     588      errno = 0;
     589      result = strtod (input, &ptr);
     590      ASSERT (result == -HUGE_VAL);       /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     591      ASSERT (ptr == input + 4);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 4.0, Solaris 9, mingw */
     592      ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
     593    }
     594    {
     595      const char input[] = "infinite";
     596      char *ptr;
     597      double result;
     598      errno = 0;
     599      result = strtod (input, &ptr);
     600      ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     601      ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     602      ASSERT (errno == 0);                /* OSF/1 4.0 */
     603    }
     604    {
     605      const char input[] = "infinitY";
     606      char *ptr;
     607      double result;
     608      errno = 0;
     609      result = strtod (input, &ptr);
     610      ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     611      ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
     612      ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
     613    }
     614    {
     615      const char input[] = "infinitY.";
     616      char *ptr;
     617      double result;
     618      errno = 0;
     619      result = strtod (input, &ptr);
     620      ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     621      ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     622      ASSERT (errno == 0);                /* OSF/1 4.0 */
     623    }
     624  
     625    /* NaN.  Some processors set the sign bit of the default NaN, so all
     626       we check is that using a sign changes the result.  */
     627    {
     628      const char input[] = "-nan";
     629      char *ptr1;
     630      char *ptr2;
     631      double result1;
     632      double result2;
     633      errno = 0;
     634      result1 = strtod (input, &ptr1);
     635      result2 = strtod (input + 1, &ptr2);
     636  #if 1 /* All known CPUs support NaNs.  */
     637      ASSERT (isnand (result1));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     638      ASSERT (isnand (result2));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     639  # if 0
     640      /* Sign bits of NaN is a portability sticking point, not worth
     641         worrying about.  */
     642      ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
     643  # endif
     644      ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
     645      ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
     646      ASSERT (errno == 0);                /* HP-UX 11.11 */
     647  #else
     648      ASSERT (result1 == 0.0);
     649      ASSERT (result2 == 0.0);
     650      ASSERT (!signbit (result1));
     651      ASSERT (!signbit (result2));
     652      ASSERT (ptr1 == input);
     653      ASSERT (ptr2 == input + 1);
     654      ASSERT (errno == 0 || errno == EINVAL);
     655  #endif
     656    }
     657    {
     658      const char input[] = "+nan(";
     659      char *ptr1;
     660      char *ptr2;
     661      double result1;
     662      double result2;
     663      errno = 0;
     664      result1 = strtod (input, &ptr1);
     665      result2 = strtod (input + 1, &ptr2);
     666  #if 1 /* All known CPUs support NaNs.  */
     667      ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     668      ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     669      ASSERT (!!signbit (result1) == !!signbit (result2));
     670      ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
     671      ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
     672      ASSERT (errno == 0);
     673  #else
     674      ASSERT (result1 == 0.0);
     675      ASSERT (result2 == 0.0);
     676      ASSERT (!signbit (result1));
     677      ASSERT (!signbit (result2));
     678      ASSERT (ptr1 == input);
     679      ASSERT (ptr2 == input + 1);
     680      ASSERT (errno == 0 || errno == EINVAL);
     681  #endif
     682    }
     683    {
     684      const char input[] = "-nan()";
     685      char *ptr1;
     686      char *ptr2;
     687      double result1;
     688      double result2;
     689      errno = 0;
     690      result1 = strtod (input, &ptr1);
     691      result2 = strtod (input + 1, &ptr2);
     692  #if 1 /* All known CPUs support NaNs.  */
     693      ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     694      ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     695  # if 0
     696      /* Sign bits of NaN is a portability sticking point, not worth
     697         worrying about.  */
     698      ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
     699  # endif
     700      ASSERT (ptr1 == input + 6);         /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     701      ASSERT (ptr2 == input + 6);         /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     702      ASSERT (errno == 0);
     703  #else
     704      ASSERT (result1 == 0.0);
     705      ASSERT (result2 == 0.0);
     706      ASSERT (!signbit (result1));
     707      ASSERT (!signbit (result2));
     708      ASSERT (ptr1 == input);
     709      ASSERT (ptr2 == input + 1);
     710      ASSERT (errno == 0 || errno == EINVAL);
     711  #endif
     712    }
     713    {
     714      const char input[] = " nan().";
     715      char *ptr;
     716      double result;
     717      errno = 0;
     718      result = strtod (input, &ptr);
     719  #if 1 /* All known CPUs support NaNs.  */
     720      ASSERT (isnand (result));           /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     721      ASSERT (ptr == input + 6);          /* glibc-2.3.6, Mac OS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     722      ASSERT (errno == 0);
     723  #else
     724      ASSERT (result == 0.0);
     725      ASSERT (!signbit (result));
     726      ASSERT (ptr == input);
     727      ASSERT (errno == 0 || errno == EINVAL);
     728  #endif
     729    }
     730    {
     731      /* The behavior of nan(0) is implementation-defined, but all
     732         implementations we know of which handle optional
     733         n-char-sequences handle nan(0) the same as nan().  */
     734      const char input[] = "-nan(0).";
     735      char *ptr1;
     736      char *ptr2;
     737      double result1;
     738      double result2;
     739      errno = 0;
     740      result1 = strtod (input, &ptr1);
     741      result2 = strtod (input + 1, &ptr2);
     742  #if 1 /* All known CPUs support NaNs.  */
     743      ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     744      ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     745  # if 0
     746      /* Sign bits of NaN is a portability sticking point, not worth
     747         worrying about.  */
     748      ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
     749  # endif
     750      ASSERT (ptr1 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     751      ASSERT (ptr2 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
     752      ASSERT (errno == 0);
     753  #else
     754      ASSERT (result1 == 0.0);
     755      ASSERT (result2 == 0.0);
     756      ASSERT (!signbit (result1));
     757      ASSERT (!signbit (result2));
     758      ASSERT (ptr1 == input);
     759      ASSERT (ptr2 == input + 1);
     760      ASSERT (errno == 0 || errno == EINVAL);
     761  #endif
     762    }
     763  
     764    /* Hex.  */
     765    {
     766      const char input[] = "0xa";
     767      char *ptr;
     768      double result;
     769      errno = 0;
     770      result = strtod (input, &ptr);
     771      ASSERT (result == 10.0);            /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     772      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     773      ASSERT (errno == 0);
     774    }
     775    {
     776      const char input[] = "0XA";
     777      char *ptr;
     778      double result;
     779      errno = 0;
     780      result = strtod (input, &ptr);
     781      ASSERT (result == 10.0);            /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     782      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     783      ASSERT (errno == 0);
     784    }
     785    {
     786      const char input[] = "0x1p";
     787      char *ptr;
     788      double result;
     789      errno = 0;
     790      result = strtod (input, &ptr);
     791      ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     792      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     793      ASSERT (errno == 0);
     794    }
     795    {
     796      const char input[] = "0x1p+";
     797      char *ptr;
     798      double result;
     799      errno = 0;
     800      result = strtod (input, &ptr);
     801      ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     802      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     803      ASSERT (errno == 0);
     804    }
     805    {
     806      const char input[] = "0x1P+";
     807      char *ptr;
     808      double result;
     809      errno = 0;
     810      result = strtod (input, &ptr);
     811      ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     812      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     813      ASSERT (errno == 0);
     814    }
     815    {
     816      const char input[] = "0x1p+1";
     817      char *ptr;
     818      double result;
     819      errno = 0;
     820      result = strtod (input, &ptr);
     821      ASSERT (result == 2.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     822      ASSERT (ptr == input + 6);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     823      ASSERT (errno == 0);
     824    }
     825    {
     826      const char input[] = "0X1P+1";
     827      char *ptr;
     828      double result;
     829      errno = 0;
     830      result = strtod (input, &ptr);
     831      ASSERT (result == 2.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     832      ASSERT (ptr == input + 6);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     833      ASSERT (errno == 0);
     834    }
     835    {
     836      const char input[] = "0x1p+1a";
     837      char *ptr;
     838      double result;
     839      errno = 0;
     840      result = strtod (input, &ptr);
     841      ASSERT (result == 2.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     842      ASSERT (ptr == input + 6);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     843      ASSERT (errno == 0);
     844    }
     845    {
     846      const char input[] = "0x1p 2";
     847      char *ptr;
     848      double result;
     849      errno = 0;
     850      result = strtod (input, &ptr);
     851      ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     852      ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
     853      ASSERT (errno == 0);
     854    }
     855  
     856    /* Large buffers.  */
     857    {
     858      size_t m = 1000000;
     859      char *input = malloc (m + 1);
     860      if (input)
     861        {
     862          char *ptr;
     863          double result;
     864          memset (input, '\t', m - 1);
     865          input[m - 1] = '1';
     866          input[m] = '\0';
     867          errno = 0;
     868          result = strtod (input, &ptr);
     869          ASSERT (result == 1.0);
     870          ASSERT (ptr == input + m);
     871          ASSERT (errno == 0);
     872        }
     873      free (input);
     874    }
     875    {
     876      size_t m = 1000000;
     877      char *input = malloc (m + 1);
     878      if (input)
     879        {
     880          char *ptr;
     881          double result;
     882          memset (input, '0', m - 1);
     883          input[m - 1] = '1';
     884          input[m] = '\0';
     885          errno = 0;
     886          result = strtod (input, &ptr);
     887          ASSERT (result == 1.0);
     888          ASSERT (ptr == input + m);
     889          ASSERT (errno == 0);
     890        }
     891      free (input);
     892    }
     893  #if 0
     894    /* Newlib has an artificial limit of 20000 for the exponent.  TODO -
     895       gnulib should fix this.  */
     896    {
     897      size_t m = 1000000;
     898      char *input = malloc (m + 1);
     899      if (input)
     900        {
     901          char *ptr;
     902          double result;
     903          input[0] = '.';
     904          memset (input + 1, '0', m - 10);
     905          input[m - 9] = '1';
     906          input[m - 8] = 'e';
     907          input[m - 7] = '+';
     908          input[m - 6] = '9';
     909          input[m - 5] = '9';
     910          input[m - 4] = '9';
     911          input[m - 3] = '9';
     912          input[m - 2] = '9';
     913          input[m - 1] = '1';
     914          input[m] = '\0';
     915          errno = 0;
     916          result = strtod (input, &ptr);
     917          ASSERT (result == 1.0);         /* Mac OS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     918          ASSERT (ptr == input + m);      /* OSF/1 5.1 */
     919          ASSERT (errno == 0);            /* Mac OS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     920        }
     921      free (input);
     922    }
     923    {
     924      size_t m = 1000000;
     925      char *input = malloc (m + 1);
     926      if (input)
     927        {
     928          char *ptr;
     929          double result;
     930          input[0] = '1';
     931          memset (input + 1, '0', m - 9);
     932          input[m - 8] = 'e';
     933          input[m - 7] = '-';
     934          input[m - 6] = '9';
     935          input[m - 5] = '9';
     936          input[m - 4] = '9';
     937          input[m - 3] = '9';
     938          input[m - 2] = '9';
     939          input[m - 1] = '1';
     940          input[m] = '\0';
     941          errno = 0;
     942          result = strtod (input, &ptr);
     943          ASSERT (result == 1.0);         /* Mac OS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     944          ASSERT (ptr == input + m);
     945          ASSERT (errno == 0);            /* Mac OS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
     946        }
     947      free (input);
     948    }
     949  #endif
     950    {
     951      size_t m = 1000000;
     952      char *input = malloc (m + 1);
     953      if (input)
     954        {
     955          char *ptr;
     956          double result;
     957          input[0] = '-';
     958          input[1] = '0';
     959          input[2] = 'e';
     960          input[3] = '1';
     961          memset (input + 4, '0', m - 3);
     962          input[m] = '\0';
     963          errno = 0;
     964          result = strtod (input, &ptr);
     965          ASSERT (result == 0.0);
     966          ASSERT (!!signbit (result) == !!signbit (minus_zerod)); /* IRIX 6.5, OSF/1 4.0 */
     967          ASSERT (ptr == input + m);
     968          ASSERT (errno == 0);
     969        }
     970      free (input);
     971    }
     972  
     973    /* Rounding.  */
     974    /* TODO - is it worth some tests of rounding for typical IEEE corner
     975       cases, such as .5 ULP rounding up to the smallest denormal and
     976       not causing underflow, or DBL_MIN - .5 ULP not causing an
     977       infinite loop?  */
     978  
     979    return status;
     980  }