1 /*
2 * Copyright (c) 1994 Cygnus Support.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * at Cygnus Support, Inc. Cygnus Support, Inc. may not be used to
11 * endorse or promote products derived from this software without
12 * specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17 /* Test conversions */
18
19 #define _GNU_SOURCE
20 #define IN_CONVERT
21 #include "test.h"
22 //#include <_ansi.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26
27 static char buffer[500];
28
29 extern double_type doubles[];
30
31 //#define GENERATE_VECTORS
32
33 /* TEST ATOF ATOFF */
34
35 double_type *pd = doubles;
36
37 #ifdef _IO_FLOAT_EXACT
38 #define CONVERT_BITS_DOUBLE 64
39 #define CONVERT_BITS_FLOAT 32
40 #else
41 #define CONVERT_BITS_DOUBLE 58
42 #define CONVERT_BITS_FLOAT 29
43 #endif
44
45 void
test_strtod(void)46 test_strtod (void)
47 {
48 char *tail;
49 double v;
50 /* On average we'll loose 1/2 a bit, so the test is for within 1 bit */
51 errno = 0;
52 v = strtod(pd->string, &tail);
53 if (tail - pd->string) {
54 if (fabs(v) < DBL_MIN && !(pd->endscan & ENDSCAN_IS_ZERO)) {
55 #ifdef NO_NEWLIB
56 /* Glibc has bugs in strtod with hex format float */
57 if (strncasecmp(pd->string, "0x", 2) == 0)
58 ;
59 else
60 #endif
61 test_eok(errno, ERANGE);
62 } else if (v == (double) INFINITY && !(pd->endscan & ENDSCAN_IS_INF))
63 test_eok(errno, ERANGE);
64 else
65 test_eok(errno, 0);
66 }
67 test_mok(v, pd->value, CONVERT_BITS_DOUBLE);
68 test_iok(tail - pd->string, pd->endscan & ENDSCAN_MASK);
69 }
70
71 void
test_strtof(void)72 test_strtof (void)
73 {
74 char *tail;
75 float v;
76 /* On average we'll loose 1/2 a bit, so the test is for within 1 bit */
77 errno = 0;
78 v = strtof(pd->string, &tail);
79 if (tail - pd->string) {
80 int e = errno;
81 if (fabsf(v) < FLT_MIN && !(pd->endscan & ENDSCAN_IS_ZERO))
82 test_eok(e, ERANGE);
83 else if (v == INFINITY && !(pd->endscan & ENDSCAN_IS_INF))
84 test_eok(errno, ERANGE);
85 else
86 test_eok(errno, 0);
87 }
88 test_mfok((double) v, pd->value, CONVERT_BITS_FLOAT);
89 test_iok(tail - pd->string, pd->endscan & ENDSCAN_MASK);
90 }
91
92 #if defined(_HAVE_LONG_DOUBLE) && (__LDBL_MANT_DIG__ == 64 || defined(TINY_STDIO))
93 #define HAVE_STRTOLD
94 #endif
95
96 #ifdef HAVE_STRTOLD
97 void
test_strtold(void)98 test_strtold (void)
99 {
100 char *tail;
101 long double v, av;
102 /* On average we'll loose 1/2 a bit, so the test is for within 1 bit */
103 errno = 0;
104 v = strtold(pd->string, &tail);
105 if (tail - pd->string) {
106 int e = errno;
107 av = v;
108 if (av < 0)
109 av = -av;
110 if (av < LDBL_MIN && !(pd->endscan & ENDSCAN_IS_ZERO))
111 test_eok(e, ERANGE);
112 else if (v == (long double) INFINITY && !(pd->endscan & ENDSCAN_IS_INF))
113 test_eok(e, ERANGE);
114 else
115 test_eok(e, 0);
116 }
117 test_mok(v, pd->value, CONVERT_BITS_DOUBLE);
118 test_iok(tail - pd->string, pd->endscan & ENDSCAN_MASK);
119 }
120 #endif
121
122 void
test_atof(void)123 test_atof (void)
124 {
125 test_mok(atof(pd->string), pd->value, CONVERT_BITS_DOUBLE);
126 }
127
128 #ifndef NO_NEWLIB
129 void
test_atoff(void)130 test_atoff (void)
131 {
132 float v = atoff(pd->string);
133 test_mfok(v, (float) pd->value, CONVERT_BITS_FLOAT);
134 }
135 #endif
136
137
138 static
139 void
iterate(void (* func)(void),char * name)140 iterate (void (*func) (void),
141 char *name)
142 {
143
144 newfunc(name);
145 pd = doubles;
146 while (pd->string) {
147 line(pd->line);
148 func();
149 pd++;
150 }
151 }
152
153
154 extern int_type ints[];
155
156 int_type *p = ints;
157
158
159 static void
int_iterate(void (* func)(),char * name)160 int_iterate (void (*func)(),
161 char *name)
162 {
163 newfunc(name);
164
165 p = ints;
166 while (p->string) {
167 line(p->line);
168 errno = 0;
169 func();
170 p++;
171 }
172 }
173
174 void
test_strtol_base(int base,int_scan_type * pi,char * string)175 test_strtol_base (int base,
176 int_scan_type *pi,
177 char *string)
178 {
179 long r;
180 char *ptr;
181 errno = 0;
182 r = strtol(string, &ptr, base);
183 test_iok(r, pi->value);
184 test_eok(errno, pi->errno_val);
185 test_iok(ptr - string, pi->end);
186 }
187
188 void
test_strtol(void)189 test_strtol (void)
190 {
191 test_strtol_base(8,&(p->octal), p->string);
192 test_strtol_base(10,&(p->decimal), p->string);
193 test_strtol_base(16, &(p->hex), p->string);
194 test_strtol_base(0, &(p->normal), p->string);
195 test_strtol_base(26, &(p->alphabetical), p->string);
196 }
197
198 void
test_atoi(void)199 test_atoi (void)
200 {
201 if (p->decimal.errno_val == 0)
202 test_iok(atoi(p->string), p->decimal.value);
203 }
204
205 void
test_atol(void)206 test_atol (void)
207 {
208 test_iok(atol(p->string), p->decimal.value);
209 test_eok(errno, p->decimal.errno_val);
210 }
211
212 extern ddouble_type ddoubles[];
213 ddouble_type *pdd;
214
215 static inline char *
check_null(char * s)216 check_null(char *s) {
217 if (s == NULL)
218 return "(out of memory)";
219 return s;
220 }
221
222 #if !defined(TINY_STDIO) && !defined(NO_NEWLIB)
223 #define ecvt_r(n, dig, dec, sign, buf, len) (ecvtbuf(n, dig, dec, sign, buf) ? 0 : -1)
224 #define fcvt_r(n, dig, dec, sign, buf, len) (fcvtbuf(n, dig, dec, sign, buf) ? 0 : -1)
225 #define ecvtf_r(n, dig, dec, sign, buf, len) (ecvtbuf(n, dig, dec, sign, buf) ? 0 : -1)
226 #define fcvtf_r(n, dig, dec, sign, buf, len) (fcvtbuf(n, dig, dec, sign, buf) ? 0 : -1)
227 #endif
228
229 /* test ECVT and friends */
230 void
test_ecvt_r(void)231 test_ecvt_r (void)
232 {
233 int a2,a3;
234 int r;
235
236 r = ecvt_r(pdd->value, pdd->e1, &a2, &a3, buffer, sizeof(buffer));
237 test_iok(0, r);
238
239 test_sok(buffer,pdd->estring);
240 test_iok(pdd->e2,a2);
241 test_iok(pdd->e3,a3);
242
243 #ifndef NO_NEWLIB
244 r = ecvtf_r(pdd->value, pdd->e1, &a2, &a3, buffer, sizeof(buffer));
245 test_iok(0, r);
246
247 test_scok(buffer,pdd->estring, 6);
248 test_iok(pdd->e2,a2);
249 test_iok(pdd->e3,a3);
250 #endif
251 }
252
253 void
test_ecvt(void)254 test_ecvt (void)
255 {
256 int a2,a3;
257 char *s;
258 s = check_null(ecvt(pdd->value, pdd->e1, &a2, &a3));
259
260 test_sok(s,pdd->estring);
261 test_iok(pdd->e2,a2);
262 test_iok(pdd->e3,a3);
263
264 #ifndef NO_NEWLIB
265 s = check_null(ecvtf(pdd->value, pdd->e1, &a2, &a3));
266
267 test_scok(s,pdd->estring, 6);
268 test_iok(pdd->e2,a2);
269 test_iok(pdd->e3,a3);
270 #endif
271 }
272
273 void
test_fcvt_r(void)274 test_fcvt_r (void)
275 {
276 int a2,a3;
277 int r;
278 r = fcvt_r(pdd->value, pdd->f1, &a2, &a3, buffer, sizeof(buffer));
279
280 test_iok(r, 0);
281 test_scok(buffer,pdd->fstring,10);
282 test_iok(pdd->f2,a2);
283 test_iok(pdd->f3,a3);
284
285 #ifndef NO_NEWLIB
286 double v1;
287 double v2;
288 static char fbuffer[sizeof(buffer)];
289 char *sde, *sfe;
290 /* Test the float version by converting and inspecting the numbers 3
291 after reconverting */
292 r = fcvtf_r(pdd->value, pdd->f1, &a2, &a3, fbuffer, sizeof(fbuffer));
293 test_iok(0, r);
294 errno = 0;
295 v1 = strtod(buffer, &sde);
296 v2 = strtod(fbuffer, &sfe);
297 /* float version may return fewer digits; expand to match */
298 int x = strlen(buffer) - strlen(fbuffer);
299 while (x-- > 0)
300 v2 *= 10;
301 if (strlen(buffer) == 0) {
302 test_iok(0, sde - buffer);
303 v1 = 0.0;
304 }
305 if (strlen(fbuffer) == 0) {
306 test_iok(0, sfe - fbuffer);
307 v2 = 0.0;
308 }
309 test_mok(v1, v2,30);
310 test_iok(pdd->f2,a2);
311 test_iok(pdd->f3,a3);
312 #endif
313 }
314
315 void
test_gcvt(void)316 test_gcvt (void)
317 {
318 char *s = check_null(gcvt(pdd->value, pdd->g1, buffer));
319 test_scok(s, pdd->gstring, 9);
320
321 #ifndef NO_NEWLIB
322 s = check_null(gcvtf(pdd->value, pdd->g1, buffer));
323 test_scok2(s, pdd->gstring, pdd->gfstring, 6);
324 #endif
325 }
326
327 void
test_fcvt(void)328 test_fcvt (void)
329 {
330 int a2,a3;
331 char *sd;
332 sd = check_null(fcvt(pdd->value, pdd->f1, &a2, &a3));
333
334 test_scok(sd,pdd->fstring,10);
335 test_iok(pdd->f2,a2);
336 test_iok(pdd->f3,a3);
337
338 #ifndef NO_NEWLIB
339 char *sf;
340 double v1;
341 double v2;
342 char *sde, *sfe;
343 /* Test the float version by converting and inspecting the numbers 3
344 after reconverting */
345 sf = check_null(fcvtf(pdd->value, pdd->f1, &a2, &a3));
346 errno = 0;
347 v1 = strtod(sd, &sde);
348 v2 = strtod(sf, &sfe);
349 /* float version may return fewer digits; expand to match */
350 int x = strlen(sd) - strlen(sf);
351 while (x-- > 0)
352 v2 *= 10;
353 if (strlen(sd) == 0) {
354 test_iok(0, sde - sd);
355 v1 = 0.0;
356 }
357 if (strlen(sf) == 0) {
358 test_iok(0, sfe - sf);
359 v2 = 0.0;
360 }
361 test_mok(v1, v2,30);
362 test_iok(pdd->f2,a2);
363 test_iok(pdd->f3,a3);
364 #endif
365 }
366
367 static void
368
diterate(void (* func)(),char * name)369 diterate (void (*func)(),
370 char *name)
371 {
372 newfunc(name);
373
374 pdd = ddoubles;
375 while (pdd->estring) {
376 line(pdd->line);
377 errno = 0;
378 func();
379 pdd++;
380 }
381 }
382
383
384 void
deltest(void)385 deltest (void)
386 {
387 #if defined(TINY_STDIO) || !defined(NO_FLOATING_POINT)
388 newfunc("rounding");
389 line(1);
390 sprintf(buffer,"%.2f", 9.999);
391 test_sok(buffer,"10.00");
392 line(2);
393 sprintf(buffer,"%.2g", 1.0);
394 test_sok(buffer,"1");
395 line(3);
396 sprintf(buffer,"%.2g", 1.2e-6);
397 test_sok(buffer,"1.2e-06");
398 line(4);
399 sprintf(buffer,"%.0g", 1.0);
400 test_sok(buffer,"1");
401 line(5);
402 sprintf(buffer,"%.0e",1e1);
403 test_sok(buffer,"1e+01");
404 line(6);
405 sprintf(buffer, "%f", 12.3456789);
406 test_sok(buffer, "12.345679");
407 line(7);
408 sprintf(buffer, "%6.3f", 12.3456789);
409 test_sok(buffer, "12.346");
410 line(8);
411 sprintf(buffer,"%.0f", 12.3456789);
412 test_sok(buffer,"12");
413 #endif
414 }
415
416 /* Most of what sprint does is tested with the tests of
417 fcvt/ecvt/gcvt, but here are some more */
418 void
test_sprint(void)419 test_sprint (void)
420 {
421 #if defined(TINY_STDIO) || !defined(NO_FLOATING_POINT)
422 extern sprint_double_type sprint_doubles[];
423 sprint_double_type *s = sprint_doubles;
424 #endif
425 extern sprint_int_type sprint_ints[];
426 sprint_int_type *si = sprint_ints;
427
428
429 newfunc( "sprintf");
430
431
432 #if defined(TINY_STDIO) || !defined(NO_FLOATING_POINT)
433 while (s->line)
434 {
435 line( s->line);
436 sprintf(buffer, s->format_string, s->value);
437 #ifdef GENERATE_VECTORS
438 if (s->mag)
439 printf("{__LINE__, %.15e,\t\"%s\", \"%s\", %d },\n",
440 s->value, buffer, s->format_string, s->mag);
441 else
442 printf("{__LINE__, %.15e,\t\"%s\", \"%s\" },\n",
443 s->value, buffer, s->format_string);
444 #else
445 test_scok(buffer, s->result, 12); /* Only check the first 12 digs,
446 other stuff is random */
447 #endif
448 s++;
449 }
450 #endif
451
452 while (si->line)
453 {
454 line( si->line);
455 if (strchr(si->format_string, 'l'))
456 sprintf(buffer, si->format_string, (long) si->value);
457 else
458 sprintf(buffer, si->format_string, si->value);
459 #ifdef GENERATE_VECTORS
460 if (si->value < 0)
461 printf("__LINE__, -%#09x,\t\"%s\", \"%s\",\n",
462 -si->value, buffer, si->format_string);
463 else
464 printf("__LINE__, %#010x,\t\"%s\", \"%s\",\n",
465 si->value, buffer, si->format_string);
466 #else
467 test_sok(buffer, si->result);
468 #endif
469 si++;
470 }
471 }
472
473 /* Scanf calls strtod etc tested elsewhere, but also has some pattern matching skills */
474 void
test_scan(void)475 test_scan (void)
476 {
477 int i,j;
478 #if defined(TINY_STDIO) || !defined(NO_FLOATING_POINT)
479 extern sprint_double_type sprint_doubles[];
480 sprint_double_type *s = sprint_doubles;
481 #endif
482 extern sprint_int_type sprint_ints[];
483 sprint_int_type *si = sprint_ints;
484
485 newfunc( "scanf");
486
487 #if defined(TINY_STDIO) || !defined(NO_FLOATING_POINT)
488 /* Test scanf by converting all the numbers in the sprint vectors
489 to and from their source and making sure nothing breaks */
490
491 while (s->line)
492 {
493
494 double d0,d1;
495 line( s->line);
496 sscanf(s->result, "%lg", &d0);
497 sprintf(buffer, "%.16e", d0);
498 sscanf(buffer, "%lg", &d1);
499 if (s->mag && s->mag < CONVERT_BITS_DOUBLE)
500 test_mok(d0, d1, s->mag);
501 else
502 test_mok(d0,d1, CONVERT_BITS_DOUBLE);
503 s++;
504 }
505 #endif
506
507 /* And integers too */
508 while (si->line)
509 {
510
511 long d0,d1;
512
513 line(si->line);
514 sscanf(si->result, "%ld", &d0);
515 sprintf(buffer, "%ld", d0);
516 sscanf(buffer, "%ld", &d1);
517 test_iok(d0,d1);
518 si++;
519 }
520
521 /* And the string matching */
522
523 sscanf(" 9","%d", &i);
524 test_iok(i, 9);
525 sscanf("foo bar 123 zap 456","foo bar %d zap %d", &i, &j);
526 test_iok(i, 123);
527 test_iok(j, 456);
528
529 sscanf("magicXYZZYfoobar","magic%[XYZ]", buffer);
530 test_sok("XYZZY", buffer);
531 sscanf("magicXYZZYfoobar","%[^XYZ]", buffer);
532 test_sok("magic", buffer);
533 }
534
535 #ifdef GENERATE_VECTORS
536 static void
gen_dvec(void)537 gen_dvec(void)
538 {
539 char ebuf[128];
540 char fbuf[128];
541 char gbuf[128];
542 int e_decpt, e_sign;
543 int f_decpt, f_sign;
544
545 strcpy(ebuf, check_null(ecvt(pdd->value, pdd->e1, &e_decpt, &e_sign)));
546 strcpy(fbuf, check_null(fcvt(pdd->value, pdd->f1, &f_decpt, &f_sign)));
547 check_null(gcvt(pdd->value, pdd->g1, gbuf));
548 printf("__LINE__, %.15e,\"%s\",%d,%d,%d,\"%s\",%d,%d,%d,\"%s\",%d,\n\n",
549 pdd->value,
550 ebuf, pdd->e1, e_decpt, e_sign,
551 fbuf, pdd->f1, f_decpt, f_sign,
552 gbuf, pdd->g1);
553 }
554 #endif
555
556 extern int _malloc_test_fail;
557
558 void
test_cvt(void)559 test_cvt (void)
560 {
561 deltest();
562
563 #ifdef GENERATE_VECTORS
564 diterate(gen_dvec, "gen");
565 #else
566 diterate(test_fcvt_r,"fcvt_r");
567 diterate(test_fcvt,"fcvt/fcvtf");
568
569 diterate(test_gcvt,"gcvt/gcvtf");
570 diterate(test_ecvt_r,"ecvt_r");
571 diterate(test_ecvt,"ecvt/ecvtf");
572 #endif
573
574 iterate(test_strtod, "strtod");
575 #ifdef HAVE_STRTOLD
576 iterate(test_strtold, "strtold");
577 #endif
578
579 test_scan();
580 test_sprint();
581 iterate(test_atof, "atof");
582 #ifndef NO_NEWLIB
583 iterate(test_atoff, "atoff");
584 #endif
585
586 iterate(test_strtof, "strtof");
587
588 int_iterate(test_atoi,"atoi");
589 if (sizeof(int) == sizeof(long)) {
590 int_iterate(test_atol,"atol");
591 int_iterate(test_strtol, "strtol");
592 }
593 }
594