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