Annotation of OpenXM_contrib/gmp/tests/misc/t-printf.c, Revision 1.1.1.1
1.1 ohara 1: /* Test gmp_printf and related functions.
2:
3: Copyright 2001, 2002 Free Software Foundation, Inc.
4:
5: This file is part of the GNU MP Library.
6:
7: The GNU MP Library is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Lesser General Public License as published by
9: the Free Software Foundation; either version 2.1 of the License, or (at your
10: option) any later version.
11:
12: The GNU MP Library is distributed in the hope that it will be useful, but
13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15: License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public License
18: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20: MA 02111-1307, USA. */
21:
22:
23: /* Usage: t-printf [-s]
24:
25: -s Check the data against the system printf, where possible. This is
26: only an option since we don't want to fail if the system printf is
27: faulty or strange. */
28:
29:
30: #include "config.h"
31:
32: #if HAVE_STDARG
33: #include <stdarg.h>
34: #else
35: #include <varargs.h>
36: #endif
37:
38: #include <stddef.h> /* for ptrdiff_t */
39: #include <stdio.h>
40: #include <stdlib.h>
41: #include <string.h>
42:
43: #if HAVE_OBSTACK_VPRINTF
44: #define obstack_chunk_alloc tests_allocate
45: #define obstack_chunk_free tests_free_nosize
46: #include <obstack.h>
47: #endif
48:
49: #if HAVE_INTTYPES_H
50: # include <inttypes.h> /* for intmax_t */
51: #else
52: # if HAVE_STDINT_H
53: # include <stdint.h>
54: # endif
55: #endif
56:
57: #if HAVE_UNISTD_H
58: #include <unistd.h> /* for unlink */
59: #endif
60:
61: #include "gmp.h"
62: #include "gmp-impl.h"
63: #include "tests.h"
64:
65:
66: int option_check_printf = 0;
67:
68:
69: #define CHECK_VFPRINTF_FILENAME "t-printf.tmp"
70: FILE *check_vfprintf_fp;
71:
72:
73: /* From any of the tests run here. */
74: #define MAX_OUTPUT 1024
75:
76:
77: void
78: #if HAVE_STDARG
79: check_plain (const char *want, const char *fmt_orig, ...)
80: #else
81: check_plain (va_alist)
82: va_dcl
83: #endif
84: {
85: char got[MAX_OUTPUT];
86: int got_len, want_len;
87: size_t fmtsize;
88: char *fmt, *q;
89: const char *p;
90: va_list ap;
91: #if HAVE_STDARG
92: va_start (ap, fmt_orig);
93: #else
94: const char *want;
95: const char *fmt_orig;
96: va_start (ap);
97: want = va_arg (ap, const char *);
98: fmt_orig = va_arg (ap, const char *);
99: #endif
100:
101: if (! option_check_printf)
102: return;
103:
104: fmtsize = strlen (fmt_orig) + 1;
105: fmt = (*__gmp_allocate_func) (fmtsize);
106:
107: for (p = fmt_orig, q = fmt; *p != '\0'; p++)
108: {
109: switch (*p) {
110: case 'a':
111: case 'A':
112: /* The exact value of the exponent isn't guaranteed in glibc, and it
113: and gmp_printf do slightly different things, so don't compare
114: directly. */
115: goto done;
116: case 'F':
117: if (p > fmt_orig && *(p-1) == '.')
118: goto done; /* don't test the "all digits" cases */
119: /* discard 'F' type */
120: break;
121: case 'Z':
122: /* transmute */
123: *q++ = 'l';
124: break;
125: default:
126: *q++ = *p;
127: break;
128: }
129: }
130: *q = '\0';
131:
132: want_len = strlen (want);
133: ASSERT_ALWAYS (want_len < sizeof(got));
134:
135: got_len = vsprintf (got, fmt, ap);
136:
137: if (got_len != want_len || strcmp (got, want) != 0)
138: {
139: printf ("wanted data doesn't match plain vsprintf\n");
140: printf (" fmt |%s|\n", fmt);
141: printf (" got |%s|\n", got);
142: printf (" want |%s|\n", want);
143: printf (" got_len %d\n", got_len);
144: printf (" want_len %d\n", want_len);
145: abort ();
146: }
147:
148: done:
149: (*__gmp_free_func) (fmt, fmtsize);
150: }
151:
152: void
153: check_vsprintf (const char *want, const char *fmt, va_list ap)
154: {
155: char got[MAX_OUTPUT];
156: int got_len, want_len;
157:
158: want_len = strlen (want);
159: got_len = gmp_vsprintf (got, fmt, ap);
160:
161: if (got_len != want_len || strcmp (got, want) != 0)
162: {
163: printf ("gmp_vsprintf wrong\n");
164: printf (" fmt |%s|\n", fmt);
165: printf (" got |%s|\n", got);
166: printf (" want |%s|\n", want);
167: printf (" got_len %d\n", got_len);
168: printf (" want_len %d\n", want_len);
169: abort ();
170: }
171: }
172:
173: void
174: check_vfprintf (const char *want, const char *fmt, va_list ap)
175: {
176: char got[MAX_OUTPUT];
177: int got_len, want_len, fread_len;
178: long ftell_len;
179:
180: want_len = strlen (want);
181:
182: rewind (check_vfprintf_fp);
183: got_len = gmp_vfprintf (check_vfprintf_fp, fmt, ap);
184: ASSERT_ALWAYS (got_len != -1);
185: ASSERT_ALWAYS (fflush (check_vfprintf_fp) == 0);
186:
187: ftell_len = ftell (check_vfprintf_fp);
188: ASSERT_ALWAYS (ftell_len != -1);
189:
190: rewind (check_vfprintf_fp);
191: ASSERT_ALWAYS (ftell_len <= sizeof(got));
192: fread_len = fread (got, 1, ftell_len, check_vfprintf_fp);
193:
194: if (got_len != want_len
195: || ftell_len != want_len
196: || fread_len != want_len
197: || memcmp (got, want, want_len) != 0)
198: {
199: printf ("gmp_vfprintf wrong\n");
200: printf (" fmt |%s|\n", fmt);
201: printf (" got |%.*s|\n", fread_len, got);
202: printf (" want |%s|\n", want);
203: printf (" got_len %d\n", got_len);
204: printf (" ftell_len %ld\n", ftell_len);
205: printf (" fread_len %d\n", fread_len);
206: printf (" want_len %d\n", want_len);
207: abort ();
208: }
209: }
210:
211: void
212: check_vsnprintf (const char *want, const char *fmt, va_list ap)
213: {
214: char got[MAX_OUTPUT+1];
215: int ret, got_len, want_len;
216: size_t bufsize;
217:
218: want_len = strlen (want);
219:
220: bufsize = -1;
221: for (;;)
222: {
223: /* do 0 to 5, then want-5 to want+5 */
224: bufsize++;
225: if (bufsize > 5 && bufsize < want_len-5)
226: bufsize = want_len-5;
227: if (bufsize > want_len + 5)
228: break;
229: ASSERT_ALWAYS (bufsize+1 <= sizeof (got));
230:
231: got[bufsize] = '!';
232: ret = gmp_vsnprintf (got, bufsize, fmt, ap);
233:
234: got_len = MIN (MAX(1,bufsize)-1, want_len);
235:
236: if (got[bufsize] != '!')
237: {
238: printf ("gmp_vsnprintf overwrote bufsize sentinel\n");
239: goto error;
240: }
241:
242: if (ret != want_len)
243: {
244: printf ("gmp_vsnprintf return value wrong\n");
245: goto error;
246: }
247:
248: if (bufsize > 0)
249: {
250: if (memcmp (got, want, got_len) != 0 || got[got_len] != '\0')
251: {
252: printf ("gmp_vsnprintf wrong result string\n");
253: error:
254: printf (" fmt |%s|\n", fmt);
255: printf (" bufsize %u\n", bufsize);
256: printf (" got |%s|\n", got);
257: printf (" want |%.*s|\n", got_len, want);
258: printf (" want full |%s|\n", want);
259: printf (" ret %d\n", ret);
260: printf (" want_len %d\n", want_len);
261: abort ();
262: }
263: }
264: }
265: }
266:
267: void
268: check_vasprintf (const char *want, const char *fmt, va_list ap)
269: {
270: char *got;
271: int got_len, want_len;
272:
273: want_len = strlen (want);
274: got_len = gmp_vasprintf (&got, fmt, ap);
275:
276: if (got_len != want_len || strcmp (got, want) != 0)
277: {
278: printf ("gmp_vasprintf wrong\n");
279: printf (" fmt |%s|\n", fmt);
280: printf (" got |%s|\n", got);
281: printf (" want |%s|\n", want);
282: printf (" got_len %d\n", got_len);
283: printf (" want_len %d\n", want_len);
284: abort ();
285: }
286: (*__gmp_free_func) (got, strlen(got)+1);
287: }
288:
289: void
290: check_obstack_vprintf (const char *want, const char *fmt, va_list ap)
291: {
292: #if HAVE_OBSTACK_VPRINTF
293: struct obstack ob;
294: int got_len, want_len, ob_len;
295: char *got;
296:
297: want_len = strlen (want);
298:
299: obstack_init (&ob);
300: got_len = gmp_obstack_vprintf (&ob, fmt, ap);
301: got = obstack_base (&ob);
302: ob_len = obstack_object_size (&ob);
303:
304: if (got_len != want_len
305: || ob_len != want_len
306: || memcmp (got, want, want_len) != 0)
307: {
308: printf ("gmp_obstack_vprintf wrong\n");
309: printf (" fmt |%s|\n", fmt);
310: printf (" got |%s|\n", got);
311: printf (" want |%s|\n", want);
312: printf (" got_len %d\n", got_len);
313: printf (" ob_len %d\n", ob_len);
314: printf (" want_len %d\n", want_len);
315: abort ();
316: }
317: obstack_free (&ob, NULL);
318: #endif
319: }
320:
321:
322: void
323: #if HAVE_STDARG
324: check_one (const char *want, const char *fmt, ...)
325: #else
326: check_one (va_alist)
327: va_dcl
328: #endif
329: {
330: va_list ap;
331: #if HAVE_STDARG
332: va_start (ap, fmt);
333: #else
334: const char *want;
335: const char *fmt;
336: va_start (ap);
337: want = va_arg (ap, const char *);
338: fmt = va_arg (ap, const char *);
339: #endif
340:
341: /* simplest first */
342: check_vsprintf (want, fmt, ap);
343: check_vfprintf (want, fmt, ap);
344: check_vsnprintf (want, fmt, ap);
345: check_vasprintf (want, fmt, ap);
346: check_obstack_vprintf (want, fmt, ap);
347: }
348:
349:
350: #define hex_or_octal_p(fmt) \
351: (strchr (fmt, 'x') != NULL \
352: || strchr (fmt, 'X') != NULL \
353: || strchr (fmt, 'o') != NULL)
354:
355: void
356: check_z (void)
357: {
358: static const struct {
359: const char *fmt;
360: const char *z;
361: const char *want;
362: } data[] = {
363: { "%Zd", "0", "0" },
364: { "%Zd", "1", "1" },
365: { "%Zd", "123", "123" },
366: { "%Zd", "-1", "-1" },
367: { "%Zd", "-123", "-123" },
368:
369: { "%+Zd", "0", "+0" },
370: { "%+Zd", "123", "+123" },
371: { "%+Zd", "-123", "-123" },
372:
373: { "%Zx", "123", "7b" },
374: { "%ZX", "123", "7B" },
375: { "%Zx", "-123", "-7b" },
376: { "%ZX", "-123", "-7B" },
377: { "%Zo", "123", "173" },
378: { "%Zo", "-123", "-173" },
379:
380: { "%#Zx", "0", "0" },
381: { "%#ZX", "0", "0" },
382: { "%#Zx", "123", "0x7b" },
383: { "%#ZX", "123", "0X7B" },
384: { "%#Zx", "-123", "-0x7b" },
385: { "%#ZX", "-123", "-0X7B" },
386:
387: { "%#Zo", "0", "0" },
388: { "%#Zo", "123", "0173" },
389: { "%#Zo", "-123", "-0173" },
390:
391: { "%10Zd", "0", " 0" },
392: { "%10Zd", "123", " 123" },
393: { "%10Zd", "-123", " -123" },
394:
395: { "%-10Zd", "0", "0 " },
396: { "%-10Zd", "123", "123 " },
397: { "%-10Zd", "-123", "-123 " },
398:
399: { "%+10Zd", "123", " +123" },
400: { "%+-10Zd", "123", "+123 " },
401: { "%+10Zd", "-123", " -123" },
402: { "%+-10Zd", "-123", "-123 " },
403:
404: { "%08Zd", "0", "00000000" },
405: { "%08Zd", "123", "00000123" },
406: { "%08Zd", "-123", "-0000123" },
407:
408: { "%+08Zd", "0", "+0000000" },
409: { "%+08Zd", "123", "+0000123" },
410: { "%+08Zd", "-123", "-0000123" },
411:
412: { "%#08Zx", "0", "00000000" },
413: { "%#08Zx", "123", "0x00007b" },
414: { "%#08Zx", "-123", "-0x0007b" },
415:
416: { "%+#08Zx", "0", "+0000000" },
417: { "%+#08Zx", "123", "+0x0007b" },
418: { "%+#08Zx", "-123", "-0x0007b" },
419:
420: { "%.0Zd", "0", "" },
421: { "%.1Zd", "0", "0" },
422: { "%.2Zd", "0", "00" },
423: { "%.3Zd", "0", "000" },
424: };
425:
426: int i, j, zeros;
427: mpz_t z;
428: char *nfmt;
429: mp_size_t nsize;
430:
431: mpz_init (z);
432:
433: for (i = 0; i < numberof (data); i++)
434: {
435: mpz_set_str_or_abort (z, data[i].z, 0);
436:
437: /* don't try negatives or forced sign in hex or octal */
438: if (mpz_fits_slong_p (z)
439: && ! (hex_or_octal_p (data[i].fmt)
440: && (strchr (data[i].fmt, '+') != NULL || mpz_sgn(z) < 0)))
441: {
442: check_plain (data[i].want, data[i].fmt, mpz_get_si (z));
443: }
444:
445: check_one (data[i].want, data[i].fmt, z);
446:
447: /* Same again, with %N and possibly some high zero limbs */
448: nfmt = __gmp_allocate_strdup (data[i].fmt);
449: for (j = 0; nfmt[j] != '\0'; j++)
450: if (nfmt[j] == 'Z')
451: nfmt[j] = 'N';
452: for (zeros = 0; zeros <= 3; zeros++)
453: {
454: nsize = ABSIZ(z)+zeros;
455: MPZ_REALLOC (z, nsize);
456: nsize = (SIZ(z) >= 0 ? nsize : -nsize);
457: refmpn_zero (PTR(z)+ABSIZ(z), zeros);
458: check_one (data[i].want, nfmt, PTR(z), nsize);
459: }
460: __gmp_free_func (nfmt, strlen(nfmt)+1);
461: }
462:
463: mpz_clear (z);
464: }
465:
466: void
467: check_q (void)
468: {
469: static const struct {
470: const char *fmt;
471: const char *q;
472: const char *want;
473: } data[] = {
474: { "%Qd", "0", "0" },
475: { "%Qd", "1", "1" },
476: { "%Qd", "123", "123" },
477: { "%Qd", "-1", "-1" },
478: { "%Qd", "-123", "-123" },
479: { "%Qd", "3/2", "3/2" },
480: { "%Qd", "-3/2", "-3/2" },
481:
482: { "%+Qd", "0", "+0" },
483: { "%+Qd", "123", "+123" },
484: { "%+Qd", "-123", "-123" },
485: { "%+Qd", "5/8", "+5/8" },
486: { "%+Qd", "-5/8", "-5/8" },
487:
488: { "%Qx", "123", "7b" },
489: { "%QX", "123", "7B" },
490: { "%Qx", "15/16", "f/10" },
491: { "%QX", "15/16", "F/10" },
492: { "%Qx", "-123", "-7b" },
493: { "%QX", "-123", "-7B" },
494: { "%Qx", "-15/16", "-f/10" },
495: { "%QX", "-15/16", "-F/10" },
496: { "%Qo", "123", "173" },
497: { "%Qo", "-123", "-173" },
498: { "%Qo", "16/17", "20/21" },
499: { "%Qo", "-16/17", "-20/21" },
500:
501: { "%#Qx", "0", "0" },
502: { "%#QX", "0", "0" },
503: { "%#Qx", "123", "0x7b" },
504: { "%#QX", "123", "0X7B" },
505: { "%#Qx", "5/8", "0x5/0x8" },
506: { "%#QX", "5/8", "0X5/0X8" },
507: { "%#Qx", "-123", "-0x7b" },
508: { "%#QX", "-123", "-0X7B" },
509: { "%#Qx", "-5/8", "-0x5/0x8" },
510: { "%#QX", "-5/8", "-0X5/0X8" },
511: { "%#Qo", "0", "0" },
512: { "%#Qo", "123", "0173" },
513: { "%#Qo", "-123", "-0173" },
514: { "%#Qo", "5/7", "05/07" },
515: { "%#Qo", "-5/7", "-05/07" },
516:
517: /* zero denominator and showbase */
518: { "%#10Qo", "0/0", " 0/0" },
519: { "%#10Qd", "0/0", " 0/0" },
520: { "%#10Qx", "0/0", " 0/0" },
521: { "%#10Qo", "123/0", " 0173/0" },
522: { "%#10Qd", "123/0", " 123/0" },
523: { "%#10Qx", "123/0", " 0x7b/0" },
524: { "%#10QX", "123/0", " 0X7B/0" },
525: { "%#10Qo", "-123/0", " -0173/0" },
526: { "%#10Qd", "-123/0", " -123/0" },
527: { "%#10Qx", "-123/0", " -0x7b/0" },
528: { "%#10QX", "-123/0", " -0X7B/0" },
529:
530: { "%10Qd", "0", " 0" },
531: { "%-10Qd", "0", "0 " },
532: { "%10Qd", "123", " 123" },
533: { "%-10Qd", "123", "123 " },
534: { "%10Qd", "-123", " -123" },
535: { "%-10Qd", "-123", "-123 " },
536:
537: { "%+10Qd", "123", " +123" },
538: { "%+-10Qd", "123", "+123 " },
539: { "%+10Qd", "-123", " -123" },
540: { "%+-10Qd", "-123", "-123 " },
541:
542: { "%08Qd", "0", "00000000" },
543: { "%08Qd", "123", "00000123" },
544: { "%08Qd", "-123", "-0000123" },
545:
546: { "%+08Qd", "0", "+0000000" },
547: { "%+08Qd", "123", "+0000123" },
548: { "%+08Qd", "-123", "-0000123" },
549:
550: { "%#08Qx", "0", "00000000" },
551: { "%#08Qx", "123", "0x00007b" },
552: { "%#08Qx", "-123", "-0x0007b" },
553:
554: { "%+#08Qx", "0", "+0000000" },
555: { "%+#08Qx", "123", "+0x0007b" },
556: { "%+#08Qx", "-123", "-0x0007b" },
557: };
558:
559: int i;
560: mpq_t q;
561:
562: mpq_init (q);
563:
564: for (i = 0; i < numberof (data); i++)
565: {
566: mpq_set_str_or_abort (q, data[i].q, 0);
567: check_one (data[i].want, data[i].fmt, q);
568: }
569:
570: mpq_clear (q);
571: }
572:
573: void
574: check_f (void)
575: {
576: static const struct {
577: const char *fmt;
578: const char *f;
579: const char *want;
580:
581: } data[] = {
582:
583: { "%Ff", "0", "0.000000" },
584: { "%Ff", "123", "123.000000" },
585: { "%Ff", "-123", "-123.000000" },
586:
587: { "%+Ff", "0", "+0.000000" },
588: { "%+Ff", "123", "+123.000000" },
589: { "%+Ff", "-123", "-123.000000" },
590:
591: { "%.0Ff", "0", "0" },
592: { "%.0Ff", "123", "123" },
593: { "%.0Ff", "-123", "-123" },
594:
595: { "%8.0Ff", "0", " 0" },
596: { "%8.0Ff", "123", " 123" },
597: { "%8.0Ff", "-123", " -123" },
598:
599: { "%08.0Ff", "0", "00000000" },
600: { "%08.0Ff", "123", "00000123" },
601: { "%08.0Ff", "-123", "-0000123" },
602:
603: { "%10.2Ff", "0", " 0.00" },
604: { "%10.2Ff", "0.25", " 0.25" },
605: { "%10.2Ff", "123.25", " 123.25" },
606: { "%10.2Ff", "-123.25", " -123.25" },
607:
608: { "%-10.2Ff", "0", "0.00 " },
609: { "%-10.2Ff", "0.25", "0.25 " },
610: { "%-10.2Ff", "123.25", "123.25 " },
611: { "%-10.2Ff", "-123.25", "-123.25 " },
612:
613: { "%.2Ff", "0.00000000000001", "0.00" },
614: { "%.2Ff", "0.002", "0.00" },
615: { "%.2Ff", "0.008", "0.01" },
616:
617: { "%.0Ff", "123.00000000000001", "123" },
618: { "%.0Ff", "123.2", "123" },
619: { "%.0Ff", "123.8", "124" },
620:
621: { "%.0Ff", "999999.9", "1000000" },
622: { "%.0Ff", "3999999.9", "4000000" },
623:
624: { "%Fe", "0", "0.000000e+00" },
625: { "%Fe", "1", "1.000000e+00" },
626: { "%Fe", "123", "1.230000e+02" },
627:
628: { "%FE", "0", "0.000000E+00" },
629: { "%FE", "1", "1.000000E+00" },
630: { "%FE", "123", "1.230000E+02" },
631:
632: { "%Fe", "0", "0.000000e+00" },
633: { "%Fe", "1", "1.000000e+00" },
634:
635: { "%.0Fe", "10000000000", "1e+10" },
636: { "%.0Fe", "-10000000000", "-1e+10" },
637:
638: { "%.2Fe", "10000000000", "1.00e+10" },
639: { "%.2Fe", "-10000000000", "-1.00e+10" },
640:
641: { "%8.0Fe", "10000000000", " 1e+10" },
642: { "%8.0Fe", "-10000000000", " -1e+10" },
643:
644: { "%-8.0Fe", "10000000000", "1e+10 " },
645: { "%-8.0Fe", "-10000000000", "-1e+10 " },
646:
647: { "%12.2Fe", "10000000000", " 1.00e+10" },
648: { "%12.2Fe", "-10000000000", " -1.00e+10" },
649:
650: { "%012.2Fe", "10000000000", "00001.00e+10" },
651: { "%012.2Fe", "-10000000000", "-0001.00e+10" },
652:
653: { "%Fg", "0", "0" },
654: { "%Fg", "1", "1" },
655: { "%Fg", "-1", "-1" },
656:
657: { "%.0Fg", "0", "0" },
658: { "%.0Fg", "1", "1" },
659: { "%.0Fg", "-1", "-1" },
660:
661: { "%.1Fg", "100", "1e+02" },
662: { "%.2Fg", "100", "1e+02" },
663: { "%.3Fg", "100", "100" },
664: { "%.4Fg", "100", "100" },
665:
666: { "%Fg", "0.001", "0.001" },
667: { "%Fg", "0.0001", "0.0001" },
668: { "%Fg", "0.00001", "1e-05" },
669: { "%Fg", "0.000001", "1e-06" },
670:
671: { "%.4Fg", "1.00000000000001", "1" },
672: { "%.4Fg", "100000000000001", "1e+14" },
673:
674: { "%.4Fg", "12345678", "1.235e+07" },
675:
676: { "%Fa", "0","0x0p+0" },
677: { "%FA", "0","0X0P+0" },
678:
679: { "%Fa", "1","0x1p+0" },
680: { "%Fa", "65535","0xf.fffp+12" },
681: { "%Fa", "65536","0x1p+16" },
682: { "%F.10a", "65536","0x1.0000000000p+16" },
683: { "%F.1a", "65535","0x1.0p+16" },
684: { "%F.0a", "65535","0x1p+16" },
685:
686: { "%.2Ff", "0.99609375", "1.00" },
687: { "%.Ff", "0.99609375", "0.99609375" },
688: { "%.Fe", "0.99609375", "9.9609375e-01" },
689: { "%.Fg", "0.99609375", "0.99609375" },
690: { "%.20Fg", "1000000", "1000000" },
691: { "%.Fg", "1000000", "1000000" },
692:
693: { "%#.0Ff", "1", "1." },
694: { "%#.0Fe", "1", "1.e+00" },
695: { "%#.0Fg", "1", "1." },
696:
697: { "%#.1Ff", "1", "1.0" },
698: { "%#.1Fe", "1", "1.0e+00" },
699: { "%#.1Fg", "1", "1." },
700:
701: { "%#.4Ff", "1234", "1234.0000" },
702: { "%#.4Fe", "1234", "1.2340e+03" },
703: { "%#.4Fg", "1234", "1234." },
704:
705: { "%#.8Ff", "1234", "1234.00000000" },
706: { "%#.8Fe", "1234", "1.23400000e+03" },
707: { "%#.8Fg", "1234", "1234.0000" },
708:
709: };
710:
711: int i;
712: mpf_t f;
713: double d;
714:
715: mpf_init2 (f, 256L);
716:
717: for (i = 0; i < numberof (data); i++)
718: {
719: if (data[i].f[0] == '0' && data[i].f[1] == 'x')
720: mpf_set_str_or_abort (f, data[i].f, 16);
721: else
722: mpf_set_str_or_abort (f, data[i].f, 10);
723:
724: /* if mpf->double doesn't truncate, then expect same result */
725: d = mpf_get_d (f);
726: if (mpf_cmp_d (f, d) == 0)
727: check_plain (data[i].want, data[i].fmt, d);
728:
729: check_one (data[i].want, data[i].fmt, f);
730: }
731:
732: mpf_clear (f);
733: }
734:
735:
736: void
737: check_n (void)
738: {
739: {
740: int n = -1;
741: check_one ("blah", "%nblah", &n);
742: ASSERT_ALWAYS (n == 0);
743: }
744:
745: {
746: int n = -1;
747: check_one ("hello ", "hello %n", &n);
748: ASSERT_ALWAYS (n == 6);
749: }
750:
751: {
752: int n = -1;
753: check_one ("hello world", "hello %n world", &n);
754: ASSERT_ALWAYS (n == 6);
755: }
756:
757: #define CHECK_N(type, string) \
758: do { \
759: type x[2]; \
760: char fmt[128]; \
761: \
762: x[0] = ~ (type) 0; \
763: x[1] = ~ (type) 0; \
764: sprintf (fmt, "%%d%%%sn%%d", string); \
765: check_one ("123456", fmt, 123, &x[0], 456); \
766: \
767: /* should write whole of x[0] and none of x[1] */ \
768: ASSERT_ALWAYS (x[0] == 3); \
769: ASSERT_ALWAYS (x[1] == (type) ~ (type) 0); \
770: \
771: } while (0)
772:
773: CHECK_N (char, "hh");
774: CHECK_N (long, "l");
775: #if HAVE_LONG_LONG
776: CHECK_N (long long, "L");
777: #endif
778: #if HAVE_INTMAX_T
779: CHECK_N (intmax_t, "j");
780: #endif
781: #if HAVE_PTRDIFF_T
782: CHECK_N (ptrdiff_t, "t");
783: #endif
784: CHECK_N (short, "h");
785: CHECK_N (size_t, "z");
786:
787: {
788: mpz_t x[2];
789: mpz_init_set_si (x[0], -987L);
790: mpz_init_set_si (x[1], 654L);
791: check_one ("123456", "%d%Zn%d", 123, x[0], 456);
792: MPZ_CHECK_FORMAT (x[0]);
793: MPZ_CHECK_FORMAT (x[1]);
794: ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
795: ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
796: mpz_clear (x[0]);
797: mpz_clear (x[1]);
798: }
799:
800: {
801: mpq_t x[2];
802: mpq_init (x[0]);
803: mpq_init (x[1]);
804: mpq_set_ui (x[0], -987L, 654L);
805: mpq_set_ui (x[1], 4115L, 226L);
806: check_one ("123456", "%d%Qn%d", 123, x[0], 456);
807: MPQ_CHECK_FORMAT (x[0]);
808: MPQ_CHECK_FORMAT (x[1]);
809: ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
810: ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
811: mpq_clear (x[0]);
812: mpq_clear (x[1]);
813: }
814:
815: {
816: mpf_t x[2];
817: mpf_init (x[0]);
818: mpf_init (x[1]);
819: mpf_set_ui (x[0], -987L);
820: mpf_set_ui (x[1], 654L);
821: check_one ("123456", "%d%Fn%d", 123, x[0], 456);
822: MPF_CHECK_FORMAT (x[0]);
823: MPF_CHECK_FORMAT (x[1]);
824: ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
825: ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
826: mpf_clear (x[0]);
827: mpf_clear (x[1]);
828: }
829:
830: {
831: mp_limb_t a[5];
832: mp_limb_t a_want[numberof(a)];
833: mp_size_t i;
834:
835: a[0] = 123;
836: check_one ("blah", "bl%Nnah", a, (mp_size_t) 0);
837: ASSERT_ALWAYS (a[0] == 123);
838:
839: MPN_ZERO (a_want, numberof (a_want));
840: for (i = 1; i < numberof (a); i++)
841: {
842: check_one ("blah", "bl%Nnah", a, i);
843: a_want[0] = 2;
844: ASSERT_ALWAYS (mpn_cmp (a, a_want, i) == 0);
845: }
846: }
847: }
848:
849:
850: void
851: check_misc (void)
852: {
853: mpz_t z;
854: mpf_t f;
855:
856: mpz_init (z);
857: mpf_init2 (f, 128L);
858:
859: check_one ("!", "%c", '!');
860:
861: check_one ("hello world", "hello %s", "world");
862: check_one ("hello:", "%s:", "hello");
863: mpz_set_ui (z, 0L);
864: check_one ("hello0", "%s%Zd", "hello", z, z);
865:
866: {
867: static char xs[801];
868: memset (xs, 'x', sizeof(xs)-1);
869: check_one (xs, "%s", xs);
870: }
871:
872: mpz_set_ui (z, 12345L);
873: check_one (" 12345", "%*Zd", 10, z);
874: check_one ("0000012345", "%0*Zd", 10, z);
875: check_one ("12345 ", "%*Zd", -10, z);
876: check_one ("12345 and 678", "%Zd and %d", z, 678);
877: check_one ("12345,1,12345,2,12345", "%Zd,%d,%Zd,%d,%Zd", z, 1, z, 2, z);
878:
879: /* from the glibc info docs */
880: mpz_set_si (z, 0L);
881: check_one ("| 0|0 | +0|+0 | 0|00000| | 00|0|",
882: "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
883: /**/ z, z, z, z, z, z, z, z, z);
884: mpz_set_si (z, 1L);
885: check_one ("| 1|1 | +1|+1 | 1|00001| 1| 01|1|",
886: "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
887: /**/ z, z, z, z, z, z, z, z, z);
888: mpz_set_si (z, -1L);
889: check_one ("| -1|-1 | -1|-1 | -1|-0001| -1| -01|-1|",
890: "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
891: /**/ z, z, z, z, z, z, z, z, z);
892: mpz_set_si (z, 100000L);
893: check_one ("|100000|100000|+100000|+100000| 100000|100000|100000|100000|100000|",
894: "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
895: /**/ z, z, z, z, z, z, z, z, z);
896: mpz_set_si (z, 0L);
897: check_one ("| 0| 0| 0| 0| 0| 0| 00000000|",
898: "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
899: /**/ z, z, z, z, z, z, z);
900: mpz_set_si (z, 1L);
901: check_one ("| 1| 1| 1| 01| 0x1| 0X1|0x00000001|",
902: "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
903: /**/ z, z, z, z, z, z, z);
904: mpz_set_si (z, 100000L);
905: check_one ("|303240|186a0|186A0|0303240|0x186a0|0X186A0|0x000186a0|",
906: "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
907: /**/ z, z, z, z, z, z, z);
908:
909: /* %zd for size_t won't be available on old systems, and running something
910: to see if it works might be bad, so only try it on glibc, and only on a
911: new enough version (glibc 2.0 doesn't have %zd) */
912: #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
913: mpz_set_ui (z, 789L);
914: check_one ("456 789 blah", "%zd %Zd blah", (size_t) 456, z);
915: #endif
916:
917: mpz_clear (z);
918: mpf_clear (f);
919: }
920:
921:
922: int
923: main (int argc, char *argv[])
924: {
925: if (argc > 1 && strcmp (argv[1], "-s") == 0)
926: option_check_printf = 1;
927:
928: tests_start ();
929: check_vfprintf_fp = fopen (CHECK_VFPRINTF_FILENAME, "w+");
930: ASSERT_ALWAYS (check_vfprintf_fp != NULL);
931:
932: check_z ();
933: check_q ();
934: check_f ();
935: check_n ();
936: check_misc ();
937:
938: ASSERT_ALWAYS (fclose (check_vfprintf_fp) == 0);
939: unlink (CHECK_VFPRINTF_FILENAME);
940: tests_end ();
941: exit (0);
942: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>