t-printf.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:25k
源码类别:

数学计算

开发平台:

Unix_Linux

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