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