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