PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/libgmp/gmp-4.3.1/tests/misc/t-printf.c

https://bitbucket.org/thelearninglabs/uclinux-distro-tll-public
C | 979 lines | 774 code | 165 blank | 40 comment | 98 complexity | f4730902ecdb271652172cd5d7db772e MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-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 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 != '\0'; 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 = '\0';
  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 vsprintf\n");
  108. printf (" fmt |%s|\n", fmt);
  109. printf (" got |%s|\n", got);
  110. printf (" want |%s|\n", want);
  111. printf (" got_len %d\n", got_len);
  112. printf (" want_len %d\n", 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 wrong\n");
  128. printf (" fmt |%s|\n", fmt);
  129. printf (" got |%s|\n", got);
  130. printf (" want |%s|\n", want);
  131. printf (" got_len %d\n", got_len);
  132. printf (" want_len %d\n", 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 wrong\n");
  158. printf (" fmt |%s|\n", fmt);
  159. printf (" got |%.*s|\n", fread_len, got);
  160. printf (" want |%s|\n", want);
  161. printf (" got_len %d\n", got_len);
  162. printf (" ftell_len %ld\n", ftell_len);
  163. printf (" fread_len %d\n", fread_len);
  164. printf (" want_len %d\n", 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 sentinel\n");
  191. goto error;
  192. }
  193. if (ret != want_len)
  194. {
  195. printf ("gmp_vsnprintf return value wrong\n");
  196. goto error;
  197. }
  198. if (bufsize > 0)
  199. {
  200. if (memcmp (got, want, got_len) != 0 || got[got_len] != '\0')
  201. {
  202. printf ("gmp_vsnprintf wrong result string\n");
  203. error:
  204. printf (" fmt |%s|\n", fmt);
  205. printf (" bufsize %lu\n", (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 %d\n", ret);
  210. printf (" want_len %d\n", 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 wrong\n");
  226. printf (" fmt |%s|\n", fmt);
  227. printf (" got |%s|\n", got);
  228. printf (" want |%s|\n", want);
  229. printf (" got_len %d\n", got_len);
  230. printf (" want_len %d\n", 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 wrong\n");
  252. printf (" fmt |%s|\n", fmt);
  253. printf (" got |%s|\n", got);
  254. printf (" want |%s|\n", want);
  255. printf (" got_len %d\n", got_len);
  256. printf (" ob_len %d\n", ob_len);
  257. printf (" want_len %d\n", 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] != '\0'; 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. \
  648. x[0] = ~ (type) 0; \
  649. x[1] = ~ (type) 0; \
  650. sprintf (fmt, "%%d%%%sn%%d", string); \
  651. check_one ("123456", fmt, 123, &x[0], 456); \
  652. \
  653. /* should write whole of x[0] and none of x[1] */ \
  654. ASSERT_ALWAYS (x[0] == 3); \
  655. ASSERT_ALWAYS (x[1] == (type) ~ (type) 0); \
  656. \
  657. } while (0)
  658. CHECK_N (mp_limb_t, "M");
  659. CHECK_N (char, "hh");
  660. CHECK_N (long, "l");
  661. #if HAVE_LONG_LONG
  662. CHECK_N (long long, "L");
  663. #endif
  664. #if HAVE_INTMAX_T
  665. CHECK_N (intmax_t, "j");
  666. #endif
  667. #if HAVE_PTRDIFF_T
  668. CHECK_N (ptrdiff_t, "t");
  669. #endif
  670. CHECK_N (short, "h");
  671. CHECK_N (size_t, "z");
  672. {
  673. mpz_t x[2];
  674. mpz_init_set_si (x[0], -987L);
  675. mpz_init_set_si (x[1], 654L);
  676. check_one ("123456", "%d%Zn%d", 123, x[0], 456);
  677. MPZ_CHECK_FORMAT (x[0]);
  678. MPZ_CHECK_FORMAT (x[1]);
  679. ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
  680. ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
  681. mpz_clear (x[0]);
  682. mpz_clear (x[1]);
  683. }
  684. {
  685. mpq_t x[2];
  686. mpq_init (x[0]);
  687. mpq_init (x[1]);
  688. mpq_set_ui (x[0], 987L, 654L);
  689. mpq_set_ui (x[1], 4115L, 226L);
  690. check_one ("123456", "%d%Qn%d", 123, x[0], 456);
  691. MPQ_CHECK_FORMAT (x[0]);
  692. MPQ_CHECK_FORMAT (x[1]);
  693. ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
  694. ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
  695. mpq_clear (x[0]);
  696. mpq_clear (x[1]);
  697. }
  698. {
  699. mpf_t x[2];
  700. mpf_init (x[0]);
  701. mpf_init (x[1]);
  702. mpf_set_ui (x[0], 987L);
  703. mpf_set_ui (x[1], 654L);
  704. check_one ("123456", "%d%Fn%d", 123, x[0], 456);
  705. MPF_CHECK_FORMAT (x[0]);
  706. MPF_CHECK_FORMAT (x[1]);
  707. ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
  708. ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
  709. mpf_clear (x[0]);
  710. mpf_clear (x[1]);
  711. }
  712. {
  713. mp_limb_t a[5];
  714. mp_limb_t a_want[numberof(a)];
  715. mp_size_t i;
  716. a[0] = 123;
  717. check_one ("blah", "bl%Nnah", a, (mp_size_t) 0);
  718. ASSERT_ALWAYS (a[0] == 123);
  719. MPN_ZERO (a_want, numberof (a_want));
  720. for (i = 1; i < numberof (a); i++)
  721. {
  722. check_one ("blah", "bl%Nnah", a, i);
  723. a_want[0] = 2;
  724. ASSERT_ALWAYS (mpn_cmp (a, a_want, i) == 0);
  725. }
  726. }
  727. }
  728. void
  729. check_misc (void)
  730. {
  731. mpz_t z;
  732. mpf_t f;
  733. mpz_init (z);
  734. mpf_init2 (f, 128L);
  735. check_one ("!", "%c", '!');
  736. check_one ("hello world", "hello %s", "world");
  737. check_one ("hello:", "%s:", "hello");
  738. mpz_set_ui (z, 0L);
  739. check_one ("hello0", "%s%Zd", "hello", z, z);
  740. {
  741. static char xs[801];
  742. memset (xs, 'x', sizeof(xs)-1);
  743. check_one (xs, "%s", xs);
  744. }
  745. mpz_set_ui (z, 12345L);
  746. check_one (" 12345", "%*Zd", 10, z);
  747. check_one ("0000012345", "%0*Zd", 10, z);
  748. check_one ("12345 ", "%*Zd", -10, z);
  749. check_one ("12345 and 678", "%Zd and %d", z, 678);
  750. check_one ("12345,1,12345,2,12345", "%Zd,%d,%Zd,%d,%Zd", z, 1, z, 2, z);
  751. /* from the glibc info docs */
  752. mpz_set_si (z, 0L);
  753. check_one ("| 0|0 | +0|+0 | 0|00000| | 00|0|",
  754. "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
  755. /**/ z, z, z, z, z, z, z, z, z);
  756. mpz_set_si (z, 1L);
  757. check_one ("| 1|1 | +1|+1 | 1|00001| 1| 01|1|",
  758. "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
  759. /**/ z, z, z, z, z, z, z, z, z);
  760. mpz_set_si (z, -1L);
  761. check_one ("| -1|-1 | -1|-1 | -1|-0001| -1| -01|-1|",
  762. "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
  763. /**/ z, z, z, z, z, z, z, z, z);
  764. mpz_set_si (z, 100000L);
  765. check_one ("|100000|100000|+100000|+100000| 100000|100000|100000|100000|100000|",
  766. "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
  767. /**/ z, z, z, z, z, z, z, z, z);
  768. mpz_set_si (z, 0L);
  769. check_one ("| 0| 0| 0| 0| 0| 0| 00000000|",
  770. "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
  771. /**/ z, z, z, z, z, z, z);
  772. mpz_set_si (z, 1L);
  773. check_one ("| 1| 1| 1| 01| 0x1| 0X1|0x00000001|",
  774. "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
  775. /**/ z, z, z, z, z, z, z);
  776. mpz_set_si (z, 100000L);
  777. check_one ("|303240|186a0|186A0|0303240|0x186a0|0X186A0|0x000186a0|",
  778. "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
  779. /**/ z, z, z, z, z, z, z);
  780. /* %zd for size_t won't be available on old systems, and running something
  781. to see if it works might be bad, so only try it on glibc, and only on a
  782. new enough version (glibc 2.0 doesn't have %zd) */
  783. #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
  784. mpz_set_ui (z, 789L);
  785. check_one ("456 789 blah", "%zd %Zd blah", (size_t) 456, z);
  786. #endif
  787. mpz_clear (z);
  788. mpf_clear (f);
  789. }
  790. int
  791. main (int argc, char *argv[])
  792. {
  793. if (argc > 1 && strcmp (argv[1], "-s") == 0)
  794. option_check_printf = 1;
  795. tests_start ();
  796. check_vfprintf_fp = fopen (CHECK_VFPRINTF_FILENAME, "w+");
  797. ASSERT_ALWAYS (check_vfprintf_fp != NULL);
  798. check_z ();
  799. check_q ();
  800. check_f ();
  801. check_limb ();
  802. check_n ();
  803. check_misc ();
  804. ASSERT_ALWAYS (fclose (check_vfprintf_fp) == 0);
  805. unlink (CHECK_VFPRINTF_FILENAME);
  806. tests_end ();
  807. exit (0);
  808. }