PageRenderTime 59ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/Libs/mpir/tests/misc/t-printf.c

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