1 | /* Copyright (C) 1991,96,97,98,99,2000,2001,2003 Free Software Foundation, Inc.
|
---|
2 | This file is part of the GNU C Library.
|
---|
3 |
|
---|
4 | The GNU C Library is free software; you can redistribute it and/or
|
---|
5 | modify it under the terms of the GNU Lesser General Public
|
---|
6 | License as published by the Free Software Foundation; either
|
---|
7 | version 2.1 of the License, or (at your option) any later version.
|
---|
8 |
|
---|
9 | The GNU C Library is distributed in the hope that it will be useful,
|
---|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
12 | Lesser General Public License for more details.
|
---|
13 |
|
---|
14 | You should have received a copy of the GNU Lesser General Public
|
---|
15 | License along with the GNU C Library; if not, write to the Free
|
---|
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
---|
17 | 02111-1307 USA. */
|
---|
18 |
|
---|
19 | #include <ctype.h>
|
---|
20 | #include <locale.h>
|
---|
21 | #include <stddef.h>
|
---|
22 | #include <stdio.h>
|
---|
23 | #include <stdlib.h>
|
---|
24 | #include <errno.h>
|
---|
25 | #include <string.h>
|
---|
26 | #include <math.h>
|
---|
27 |
|
---|
28 | struct ltest
|
---|
29 | {
|
---|
30 | const char *str; /* Convert this. */
|
---|
31 | double expect; /* To get this. */
|
---|
32 | char left; /* With this left over. */
|
---|
33 | int err; /* And this in errno. */
|
---|
34 | };
|
---|
35 | static const struct ltest tests[] =
|
---|
36 | {
|
---|
37 | { "12.345", 12.345, '\0', 0 },
|
---|
38 | { "12.345e19", 12.345e19, '\0', 0 },
|
---|
39 | { "-.1e+9", -.1e+9, '\0', 0 },
|
---|
40 | { ".125", .125, '\0', 0 },
|
---|
41 | { "1e20", 1e20, '\0', 0 },
|
---|
42 | { "0e-19", 0, '\0', 0 },
|
---|
43 | { "4\00012", 4.0, '\0', 0 },
|
---|
44 | { "5.9e-76", 5.9e-76, '\0', 0 },
|
---|
45 | { "0x1.4p+3", 10.0, '\0', 0 },
|
---|
46 | { "0xAp0", 10.0, '\0', 0 },
|
---|
47 | { "0x0Ap0", 10.0, '\0', 0 },
|
---|
48 | { "0x0A", 10.0, '\0', 0 },
|
---|
49 | { "0xA0", 160.0, '\0', 0 },
|
---|
50 | { "0x0.A0p8", 160.0, '\0', 0 },
|
---|
51 | { "0x0.50p9", 160.0, '\0', 0 },
|
---|
52 | { "0x0.28p10", 160.0, '\0', 0 },
|
---|
53 | { "0x0.14p11", 160.0, '\0', 0 },
|
---|
54 | { "0x0.0A0p12", 160.0, '\0', 0 },
|
---|
55 | { "0x0.050p13", 160.0, '\0', 0 },
|
---|
56 | { "0x0.028p14", 160.0, '\0', 0 },
|
---|
57 | { "0x0.014p15", 160.0, '\0', 0 },
|
---|
58 | { "0x00.00A0p16", 160.0, '\0', 0 },
|
---|
59 | { "0x00.0050p17", 160.0, '\0', 0 },
|
---|
60 | { "0x00.0028p18", 160.0, '\0', 0 },
|
---|
61 | { "0x00.0014p19", 160.0, '\0', 0 },
|
---|
62 | { "0x1p-1023",
|
---|
63 | 1.11253692925360069154511635866620203210960799023116591527666e-308,
|
---|
64 | '\0', 0 },
|
---|
65 | { "0x0.8p-1022",
|
---|
66 | 1.11253692925360069154511635866620203210960799023116591527666e-308,
|
---|
67 | '\0', 0 },
|
---|
68 | #if __GNUC_PREREQ(2,96)
|
---|
69 | /* For older GCC release HUGE_VAL is not a constant. */
|
---|
70 | { "Inf", HUGE_VAL, '\0', 0 },
|
---|
71 | { "-Inf", -HUGE_VAL, '\0', 0 },
|
---|
72 | { "+InFiNiTy", HUGE_VAL, '\0', 0 },
|
---|
73 | #endif
|
---|
74 | { "0x80000Ap-23", 0x80000Ap-23, '\0', 0 },
|
---|
75 | { NULL, 0, '\0', 0 }
|
---|
76 | };
|
---|
77 |
|
---|
78 | static void expand (char *dst, int c);
|
---|
79 | static int long_dbl (void);
|
---|
80 | static int locale_test (void);
|
---|
81 |
|
---|
82 | int
|
---|
83 | main (int argc, char ** argv)
|
---|
84 | {
|
---|
85 | char buf[100];
|
---|
86 | register const struct ltest *lt;
|
---|
87 | char *ep;
|
---|
88 | int status = 0;
|
---|
89 | int save_errno;
|
---|
90 |
|
---|
91 | for (lt = tests; lt->str != NULL; ++lt)
|
---|
92 | {
|
---|
93 | double d;
|
---|
94 |
|
---|
95 | errno = 0;
|
---|
96 | d = strtod(lt->str, &ep);
|
---|
97 | save_errno = errno;
|
---|
98 | printf ("strtod (\"%s\") test %u",
|
---|
99 | lt->str, (unsigned int) (lt - tests));
|
---|
100 | if (d == lt->expect && *ep == lt->left && save_errno == lt->err)
|
---|
101 | puts ("\tOK");
|
---|
102 | else
|
---|
103 | {
|
---|
104 | puts ("\tBAD");
|
---|
105 | if (d != lt->expect)
|
---|
106 | printf (" returns %.60g, expected %.60g\n", d, lt->expect);
|
---|
107 | if (lt->left != *ep)
|
---|
108 | {
|
---|
109 | char exp1[5], exp2[5];
|
---|
110 | expand (exp1, *ep);
|
---|
111 | expand (exp2, lt->left);
|
---|
112 | printf (" leaves '%s', expected '%s'\n", exp1, exp2);
|
---|
113 | }
|
---|
114 | if (save_errno != lt->err)
|
---|
115 | printf (" errno %d (%s) instead of %d (%s)\n",
|
---|
116 | save_errno, strerror (save_errno),
|
---|
117 | lt->err, strerror (lt->err));
|
---|
118 | status = 1;
|
---|
119 | }
|
---|
120 | }
|
---|
121 |
|
---|
122 | sprintf (buf, "%f", strtod ("-0.0", NULL));
|
---|
123 | if (strcmp (buf, "-0.000000") != 0)
|
---|
124 | {
|
---|
125 | printf (" strtod (\"-0.0\", NULL) returns \"%s\"\n", buf);
|
---|
126 | status = 1;
|
---|
127 | }
|
---|
128 |
|
---|
129 | const char input[] = "3752432815e-39";
|
---|
130 |
|
---|
131 | float f1 = strtold (input, NULL);
|
---|
132 | float f2;
|
---|
133 | float f3 = strtof (input, NULL);
|
---|
134 | sscanf (input, "%g", &f2);
|
---|
135 |
|
---|
136 | if (f1 != f2)
|
---|
137 | {
|
---|
138 | printf ("f1 = %a != f2 = %a\n", f1, f2);
|
---|
139 | status = 1;
|
---|
140 | }
|
---|
141 | if (f1 != f3)
|
---|
142 | {
|
---|
143 | printf ("f1 = %a != f3 = %a\n", f1, f3);
|
---|
144 | status = 1;
|
---|
145 | }
|
---|
146 | if (f2 != f3)
|
---|
147 | {
|
---|
148 | printf ("f2 = %a != f3 = %a\n", f2, f3);
|
---|
149 | status = 1;
|
---|
150 | }
|
---|
151 |
|
---|
152 | const char input2[] = "+1.000000000116415321826934814453125";
|
---|
153 | if (strtold (input2, NULL) != +1.000000000116415321826934814453125L)
|
---|
154 | {
|
---|
155 | printf ("input2: %La != %La\n", strtold (input2, NULL),
|
---|
156 | +1.000000000116415321826934814453125L);
|
---|
157 | status = 1;
|
---|
158 | }
|
---|
159 |
|
---|
160 | static struct { const char *str; long double l; } ltests[] =
|
---|
161 | {
|
---|
162 | { "42.0000000000000000001", 42.0000000000000000001L },
|
---|
163 | { "42.00000000000000000001", 42.00000000000000000001L },
|
---|
164 | { "42.000000000000000000001", 42.000000000000000000001L }
|
---|
165 | };
|
---|
166 | int n;
|
---|
167 | for (n = 0; n < sizeof (ltests) / sizeof (ltests[0]); ++n)
|
---|
168 | if (strtold (ltests[n].str, NULL) != ltests[n].l)
|
---|
169 | {
|
---|
170 | printf ("ltests[%d]: %La != %La\n", n,
|
---|
171 | strtold (ltests[n].str, NULL), ltests[n].l);
|
---|
172 | status = 1;
|
---|
173 | }
|
---|
174 |
|
---|
175 | status |= long_dbl ();
|
---|
176 |
|
---|
177 | status |= locale_test ();
|
---|
178 |
|
---|
179 | return status ? EXIT_FAILURE : EXIT_SUCCESS;
|
---|
180 | }
|
---|
181 |
|
---|
182 | static void
|
---|
183 | expand (dst, c)
|
---|
184 | char *dst;
|
---|
185 | register int c;
|
---|
186 | {
|
---|
187 | if (isprint (c))
|
---|
188 | {
|
---|
189 | dst[0] = c;
|
---|
190 | dst[1] = '\0';
|
---|
191 | }
|
---|
192 | else
|
---|
193 | (void) sprintf (dst, "%#.3o", (unsigned int) c);
|
---|
194 | }
|
---|
195 |
|
---|
196 | static int
|
---|
197 | long_dbl (void)
|
---|
198 | {
|
---|
199 | /* Regenerate this string using
|
---|
200 |
|
---|
201 | echo '(2^53-1)*2^(1024-53)' | bc | sed 's/\([^\]*\)\\*$/ "\1"/'
|
---|
202 |
|
---|
203 | */
|
---|
204 | static const char longestdbl[] =
|
---|
205 | "17976931348623157081452742373170435679807056752584499659891747680315"
|
---|
206 | "72607800285387605895586327668781715404589535143824642343213268894641"
|
---|
207 | "82768467546703537516986049910576551282076245490090389328944075868508"
|
---|
208 | "45513394230458323690322294816580855933212334827479782620414472316873"
|
---|
209 | "8177180919299881250404026184124858368";
|
---|
210 | double d = strtod (longestdbl, NULL);
|
---|
211 |
|
---|
212 | printf ("strtod (\"%s\", NULL) = %g\n", longestdbl, d);
|
---|
213 |
|
---|
214 | if (d != 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)
|
---|
215 | return 1;
|
---|
216 |
|
---|
217 | return 0;
|
---|
218 | }
|
---|
219 |
|
---|
220 | /* Perform a few tests in a locale with thousands separators. */
|
---|
221 | static int
|
---|
222 | locale_test (void)
|
---|
223 | {
|
---|
224 | static const struct
|
---|
225 | {
|
---|
226 | const char *loc;
|
---|
227 | const char *str;
|
---|
228 | double exp;
|
---|
229 | ptrdiff_t nread;
|
---|
230 | } tests[] =
|
---|
231 | {
|
---|
232 | { "de_DE.UTF-8", "1,5", 1.5, 3 },
|
---|
233 | { "de_DE.UTF-8", "1.5", 1.0, 1 },
|
---|
234 | { "de_DE.UTF-8", "1.500", 1500.0, 5 },
|
---|
235 | { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65, 26 }
|
---|
236 | };
|
---|
237 | #define ntests (sizeof (tests) / sizeof (tests[0]))
|
---|
238 | size_t n;
|
---|
239 | int result = 0;
|
---|
240 |
|
---|
241 | puts ("\nLocale tests");
|
---|
242 |
|
---|
243 | for (n = 0; n < ntests; ++n)
|
---|
244 | {
|
---|
245 | double d;
|
---|
246 | char *endp;
|
---|
247 |
|
---|
248 | if (setlocale (LC_ALL, tests[n].loc) == NULL)
|
---|
249 | {
|
---|
250 | printf ("cannot set locale %s\n", tests[n].loc);
|
---|
251 | result = 1;
|
---|
252 | continue;
|
---|
253 | }
|
---|
254 |
|
---|
255 | /* We call __strtod_interal here instead of strtod to tests the
|
---|
256 | handling of grouping. */
|
---|
257 | d = __strtod_internal (tests[n].str, &endp, 1);
|
---|
258 | if (d != tests[n].exp)
|
---|
259 | {
|
---|
260 | printf ("strtod(\"%s\") returns %g and not %g\n",
|
---|
261 | tests[n].str, d, tests[n].exp);
|
---|
262 | result = 1;
|
---|
263 | }
|
---|
264 | else if (endp - tests[n].str != tests[n].nread)
|
---|
265 | {
|
---|
266 | printf ("strtod(\"%s\") read %td bytes and not %td\n",
|
---|
267 | tests[n].str, endp - tests[n].str, tests[n].nread);
|
---|
268 | result = 1;
|
---|
269 | }
|
---|
270 | }
|
---|
271 |
|
---|
272 | if (result == 0)
|
---|
273 | puts ("all OK");
|
---|
274 |
|
---|
275 | return result;
|
---|
276 | }
|
---|