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