github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/misc/t-scanf.c (about) 1 /* Test gmp_scanf and related functions. 2 3 Copyright 2001-2004 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-scanf [-s] 22 23 -s Check the data against the system scanf, where possible. This is 24 only an option since we don't want to fail if the system scanf is 25 faulty or strange. 26 27 There's some fairly unattractive repetition between check_z, check_q and 28 check_f, but enough differences to make a common loop or a set of macros 29 seem like too much trouble. */ 30 31 #include "config.h" /* needed for the HAVE_, could also move gmp incls */ 32 33 #include <stdarg.h> 34 35 #include <stddef.h> /* for ptrdiff_t */ 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #if HAVE_INTTYPES_H 41 # include <inttypes.h> /* for intmax_t */ 42 #else 43 # if HAVE_STDINT_H 44 # include <stdint.h> 45 # endif 46 #endif 47 48 #if HAVE_UNISTD_H 49 #include <unistd.h> /* for unlink */ 50 #endif 51 52 #include "gmp.h" 53 #include "gmp-impl.h" 54 #include "tests.h" 55 56 57 #define TEMPFILE "t-scanf.tmp" 58 59 int option_libc_scanf = 0; 60 61 typedef int (*fun_t) (const char *, const char *, void *, void *); 62 63 64 /* This problem was seen on powerpc7450-apple-darwin7.0.0, sscanf returns 0 65 where it should return EOF. A workaround in gmp_sscanf would be a bit 66 tedious, and since this is a rather obvious libc bug, quite likely 67 affecting other programs, we'll just suppress affected tests for now. */ 68 int 69 test_sscanf_eof_ok (void) 70 { 71 static int result = -1; 72 73 if (result == -1) 74 { 75 int x; 76 if (sscanf ("", "%d", &x) == EOF) 77 { 78 result = 1; 79 } 80 else 81 { 82 printf ("Warning, sscanf(\"\",\"%%d\",&x) doesn't return EOF.\n"); 83 printf ("This affects gmp_sscanf, tests involving it will be suppressed.\n"); 84 printf ("You should try to get a fix for your libc.\n"); 85 result = 0; 86 } 87 } 88 return result; 89 } 90 91 92 /* Convert fmt from a GMP scanf format string to an equivalent for a plain 93 libc scanf, for example "%Zd" becomes "%ld". Return 1 if this succeeds, 94 0 if it cannot (or should not) be done. */ 95 int 96 libc_scanf_convert (char *fmt) 97 { 98 char *p = fmt; 99 100 if (! option_libc_scanf) 101 return 0; 102 103 for ( ; *fmt != '\0'; fmt++) 104 { 105 switch (*fmt) { 106 case 'F': 107 case 'Q': 108 case 'Z': 109 /* transmute */ 110 *p++ = 'l'; 111 break; 112 default: 113 *p++ = *fmt; 114 break; 115 } 116 } 117 *p = '\0'; 118 return 1; 119 } 120 121 122 long got_ftell; 123 int fromstring_next_c; 124 125 /* Call gmp_fscanf, reading the "input" string data provided. */ 126 int 127 fromstring_gmp_fscanf (const char *input, const char *fmt, ...) 128 { 129 va_list ap; 130 FILE *fp; 131 int ret; 132 va_start (ap, fmt); 133 134 fp = fopen (TEMPFILE, "w+"); 135 ASSERT_ALWAYS (fp != NULL); 136 ASSERT_ALWAYS (fputs (input, fp) != EOF); 137 ASSERT_ALWAYS (fflush (fp) == 0); 138 rewind (fp); 139 140 ret = gmp_vfscanf (fp, fmt, ap); 141 got_ftell = ftell (fp); 142 ASSERT_ALWAYS (got_ftell != -1L); 143 144 fromstring_next_c = getc (fp); 145 146 ASSERT_ALWAYS (fclose (fp) == 0); 147 va_end (ap); 148 return ret; 149 } 150 151 152 int 153 fun_gmp_sscanf (const char *input, const char *fmt, void *a1, void *a2) 154 { 155 if (a2 == NULL) 156 return gmp_sscanf (input, fmt, a1); 157 else 158 return gmp_sscanf (input, fmt, a1, a2); 159 } 160 161 int 162 fun_gmp_fscanf (const char *input, const char *fmt, void *a1, void *a2) 163 { 164 if (a2 == NULL) 165 return fromstring_gmp_fscanf (input, fmt, a1); 166 else 167 return fromstring_gmp_fscanf (input, fmt, a1, a2); 168 } 169 170 171 int 172 fun_fscanf (const char *input, const char *fmt, void *a1, void *a2) 173 { 174 FILE *fp; 175 int ret; 176 177 fp = fopen (TEMPFILE, "w+"); 178 ASSERT_ALWAYS (fp != NULL); 179 ASSERT_ALWAYS (fputs (input, fp) != EOF); 180 ASSERT_ALWAYS (fflush (fp) == 0); 181 rewind (fp); 182 183 if (a2 == NULL) 184 ret = fscanf (fp, fmt, a1); 185 else 186 ret = fscanf (fp, fmt, a1, a2); 187 188 got_ftell = ftell (fp); 189 ASSERT_ALWAYS (got_ftell != -1L); 190 191 fromstring_next_c = getc (fp); 192 193 ASSERT_ALWAYS (fclose (fp) == 0); 194 return ret; 195 } 196 197 198 /* On various old systems, for instance HP-UX 9, the C library sscanf needs 199 to be able to write into the input string. Ensure that this is possible, 200 when gcc is putting the test data into a read-only section. 201 202 Actually we ought to only need this under SSCANF_WRITABLE_INPUT from 203 configure, but it's just as easy to do it unconditionally, and in any 204 case this code is only executed under the -s option. */ 205 206 int 207 fun_sscanf (const char *input, const char *fmt, void *a1, void *a2) 208 { 209 char *input_writable; 210 size_t size; 211 int ret; 212 213 size = strlen (input) + 1; 214 input_writable = (char *) (*__gmp_allocate_func) (size); 215 memcpy (input_writable, input, size); 216 217 if (a2 == NULL) 218 ret = sscanf (input_writable, fmt, a1); 219 else 220 ret = sscanf (input_writable, fmt, a1, a2); 221 222 (*__gmp_free_func) (input_writable, size); 223 return ret; 224 } 225 226 227 /* whether the format string consists entirely of ignored fields */ 228 int 229 fmt_allignore (const char *fmt) 230 { 231 int saw_star = 1; 232 for ( ; *fmt != '\0'; fmt++) 233 { 234 switch (*fmt) { 235 case '%': 236 if (! saw_star) 237 return 0; 238 saw_star = 0; 239 break; 240 case '*': 241 saw_star = 1; 242 break; 243 } 244 } 245 return 1; 246 } 247 248 void 249 check_z (void) 250 { 251 static const struct { 252 const char *fmt; 253 const char *input; 254 const char *want; 255 int want_ret; 256 long want_ftell; 257 int want_upto; 258 int not_glibc; 259 260 } data[] = { 261 262 { "%Zd", "0", "0", 1, -1, -1 }, 263 { "%Zd", "1", "1", 1, -1, -1 }, 264 { "%Zd", "123", "123", 1, -1, -1 }, 265 { "%Zd", "+0", "0", 1, -1, -1 }, 266 { "%Zd", "+1", "1", 1, -1, -1 }, 267 { "%Zd", "+123", "123", 1, -1, -1 }, 268 { "%Zd", "-0", "0", 1, -1, -1 }, 269 { "%Zd", "-1", "-1", 1, -1, -1 }, 270 { "%Zd", "-123", "-123", 1, -1, -1 }, 271 272 { "%Zo", "0", "0", 1, -1, -1 }, 273 { "%Zo", "173", "123", 1, -1, -1 }, 274 { "%Zo", "+0", "0", 1, -1, -1 }, 275 { "%Zo", "+173", "123", 1, -1, -1 }, 276 { "%Zo", "-0", "0", 1, -1, -1 }, 277 { "%Zo", "-173", "-123", 1, -1, -1 }, 278 279 { "%Zx", "0", "0", 1, -1, -1 }, 280 { "%Zx", "7b", "123", 1, -1, -1 }, 281 { "%Zx", "7b", "123", 1, -1, -1 }, 282 { "%Zx", "+0", "0", 1, -1, -1 }, 283 { "%Zx", "+7b", "123", 1, -1, -1 }, 284 { "%Zx", "+7b", "123", 1, -1, -1 }, 285 { "%Zx", "-0", "-0", 1, -1, -1 }, 286 { "%Zx", "-7b", "-123", 1, -1, -1 }, 287 { "%Zx", "-7b", "-123", 1, -1, -1 }, 288 { "%ZX", "0", "0", 1, -1, -1 }, 289 { "%ZX", "7b", "123", 1, -1, -1 }, 290 { "%ZX", "7b", "123", 1, -1, -1 }, 291 { "%ZX", "+0", "0", 1, -1, -1 }, 292 { "%ZX", "+7b", "123", 1, -1, -1 }, 293 { "%ZX", "+7b", "123", 1, -1, -1 }, 294 { "%ZX", "-0", "-0", 1, -1, -1 }, 295 { "%ZX", "-7b", "-123", 1, -1, -1 }, 296 { "%ZX", "-7b", "-123", 1, -1, -1 }, 297 { "%Zx", "0", "0", 1, -1, -1 }, 298 { "%Zx", "7B", "123", 1, -1, -1 }, 299 { "%Zx", "7B", "123", 1, -1, -1 }, 300 { "%Zx", "+0", "0", 1, -1, -1 }, 301 { "%Zx", "+7B", "123", 1, -1, -1 }, 302 { "%Zx", "+7B", "123", 1, -1, -1 }, 303 { "%Zx", "-0", "-0", 1, -1, -1 }, 304 { "%Zx", "-7B", "-123", 1, -1, -1 }, 305 { "%Zx", "-7B", "-123", 1, -1, -1 }, 306 { "%ZX", "0", "0", 1, -1, -1 }, 307 { "%ZX", "7B", "123", 1, -1, -1 }, 308 { "%ZX", "7B", "123", 1, -1, -1 }, 309 { "%ZX", "+0", "0", 1, -1, -1 }, 310 { "%ZX", "+7B", "123", 1, -1, -1 }, 311 { "%ZX", "+7B", "123", 1, -1, -1 }, 312 { "%ZX", "-0", "-0", 1, -1, -1 }, 313 { "%ZX", "-7B", "-123", 1, -1, -1 }, 314 { "%ZX", "-7B", "-123", 1, -1, -1 }, 315 316 { "%Zi", "0", "0", 1, -1, -1 }, 317 { "%Zi", "1", "1", 1, -1, -1 }, 318 { "%Zi", "123", "123", 1, -1, -1 }, 319 { "%Zi", "+0", "0", 1, -1, -1 }, 320 { "%Zi", "+1", "1", 1, -1, -1 }, 321 { "%Zi", "+123", "123", 1, -1, -1 }, 322 { "%Zi", "-0", "0", 1, -1, -1 }, 323 { "%Zi", "-1", "-1", 1, -1, -1 }, 324 { "%Zi", "-123", "-123", 1, -1, -1 }, 325 326 { "%Zi", "00", "0", 1, -1, -1 }, 327 { "%Zi", "0173", "123", 1, -1, -1 }, 328 { "%Zi", "+00", "0", 1, -1, -1 }, 329 { "%Zi", "+0173", "123", 1, -1, -1 }, 330 { "%Zi", "-00", "0", 1, -1, -1 }, 331 { "%Zi", "-0173", "-123", 1, -1, -1 }, 332 333 { "%Zi", "0x0", "0", 1, -1, -1 }, 334 { "%Zi", "0x7b", "123", 1, -1, -1 }, 335 { "%Zi", "0x7b", "123", 1, -1, -1 }, 336 { "%Zi", "+0x0", "0", 1, -1, -1 }, 337 { "%Zi", "+0x7b", "123", 1, -1, -1 }, 338 { "%Zi", "+0x7b", "123", 1, -1, -1 }, 339 { "%Zi", "-0x0", "-0", 1, -1, -1 }, 340 { "%Zi", "-0x7b", "-123", 1, -1, -1 }, 341 { "%Zi", "-0x7b", "-123", 1, -1, -1 }, 342 { "%Zi", "0X0", "0", 1, -1, -1 }, 343 { "%Zi", "0X7b", "123", 1, -1, -1 }, 344 { "%Zi", "0X7b", "123", 1, -1, -1 }, 345 { "%Zi", "+0X0", "0", 1, -1, -1 }, 346 { "%Zi", "+0X7b", "123", 1, -1, -1 }, 347 { "%Zi", "+0X7b", "123", 1, -1, -1 }, 348 { "%Zi", "-0X0", "-0", 1, -1, -1 }, 349 { "%Zi", "-0X7b", "-123", 1, -1, -1 }, 350 { "%Zi", "-0X7b", "-123", 1, -1, -1 }, 351 { "%Zi", "0x0", "0", 1, -1, -1 }, 352 { "%Zi", "0x7B", "123", 1, -1, -1 }, 353 { "%Zi", "0x7B", "123", 1, -1, -1 }, 354 { "%Zi", "+0x0", "0", 1, -1, -1 }, 355 { "%Zi", "+0x7B", "123", 1, -1, -1 }, 356 { "%Zi", "+0x7B", "123", 1, -1, -1 }, 357 { "%Zi", "-0x0", "-0", 1, -1, -1 }, 358 { "%Zi", "-0x7B", "-123", 1, -1, -1 }, 359 { "%Zi", "-0x7B", "-123", 1, -1, -1 }, 360 { "%Zi", "0X0", "0", 1, -1, -1 }, 361 { "%Zi", "0X7B", "123", 1, -1, -1 }, 362 { "%Zi", "0X7B", "123", 1, -1, -1 }, 363 { "%Zi", "+0X0", "0", 1, -1, -1 }, 364 { "%Zi", "+0X7B", "123", 1, -1, -1 }, 365 { "%Zi", "+0X7B", "123", 1, -1, -1 }, 366 { "%Zi", "-0X0", "-0", 1, -1, -1 }, 367 { "%Zi", "-0X7B", "-123", 1, -1, -1 }, 368 { "%Zi", "-0X7B", "-123", 1, -1, -1 }, 369 370 { "%Zd", " 0", "0", 1, -1, -1 }, 371 { "%Zd", " 0", "0", 1, -1, -1 }, 372 { "%Zd", " 0", "0", 1, -1, -1 }, 373 { "%Zd", "\t0", "0", 1, -1, -1 }, 374 { "%Zd", "\t\t0", "0", 1, -1, -1 }, 375 376 { "hello%Zd", "hello0", "0", 1, -1, -1 }, 377 { "hello%Zd", "hello 0", "0", 1, -1, -1 }, 378 { "hello%Zd", "hello \t0", "0", 1, -1, -1 }, 379 { "hello%Zdworld", "hello 0world", "0", 1, -1, -1 }, 380 381 { "hello%*Zd", "hello0", "-999", 0, -1, -1 }, 382 { "hello%*Zd", "hello 0", "-999", 0, -1, -1 }, 383 { "hello%*Zd", "hello \t0", "-999", 0, -1, -1 }, 384 { "hello%*Zdworld", "hello 0world", "-999", 0, -1, -1 }, 385 386 { "%Zd", "", "-999", -1, -1, -555 }, 387 { "%Zd", " ", "-999", -1, -1, -555 }, 388 { " %Zd", "", "-999", -1, -1, -555 }, 389 { "xyz%Zd", "", "-999", -1, -1, -555 }, 390 391 { "%*Zd", "", "-999", -1, -1, -555 }, 392 { " %*Zd", "", "-999", -1, -1, -555 }, 393 { "xyz%*Zd", "", "-999", -1, -1, -555 }, 394 395 { "%Zd", "xyz", "0", 0, 0, -555 }, 396 397 /* match something, but invalid */ 398 { "%Zd", "-", "-999", 0, 1, -555 }, 399 { "%Zd", "+", "-999", 0, 1, -555 }, 400 { "xyz%Zd", "xyz-", "-999", 0, 4, -555 }, 401 { "xyz%Zd", "xyz+", "-999", 0, 4, -555 }, 402 { "%Zi", "0x", "-999", 0, 2, -555 }, 403 { "%Zi", "0X", "-999", 0, 2, -555 }, 404 { "%Zi", "0x-", "-999", 0, 2, -555 }, 405 { "%Zi", "0X+", "-999", 0, 2, -555 }, 406 { "%Zi", "-0x", "-999", 0, 3, -555 }, 407 { "%Zi", "-0X", "-999", 0, 3, -555 }, 408 { "%Zi", "+0x", "-999", 0, 3, -555 }, 409 { "%Zi", "+0X", "-999", 0, 3, -555 }, 410 411 { "%1Zi", "1234", "1", 1, 1, 1 }, 412 { "%2Zi", "1234", "12", 1, 2, 2 }, 413 { "%3Zi", "1234", "123", 1, 3, 3 }, 414 { "%4Zi", "1234", "1234", 1, 4, 4 }, 415 { "%5Zi", "1234", "1234", 1, 4, 4 }, 416 { "%6Zi", "1234", "1234", 1, 4, 4 }, 417 418 { "%1Zi", "01234", "0", 1, 1, 1 }, 419 { "%2Zi", "01234", "01", 1, 2, 2 }, 420 { "%3Zi", "01234", "012", 1, 3, 3 }, 421 { "%4Zi", "01234", "0123", 1, 4, 4 }, 422 { "%5Zi", "01234", "01234", 1, 5, 5 }, 423 { "%6Zi", "01234", "01234", 1, 5, 5 }, 424 { "%7Zi", "01234", "01234", 1, 5, 5 }, 425 426 { "%1Zi", "0x1234", "0", 1, 1, 1 }, 427 { "%2Zi", "0x1234", "-999", 0, 2, -555 }, 428 { "%3Zi", "0x1234", "0x1", 1, 3, 3 }, 429 { "%4Zi", "0x1234", "0x12", 1, 4, 4 }, 430 { "%5Zi", "0x1234", "0x123", 1, 5, 5 }, 431 { "%6Zi", "0x1234", "0x1234", 1, 6, 6 }, 432 { "%7Zi", "0x1234", "0x1234", 1, 6, 6 }, 433 { "%8Zi", "0x1234", "0x1234", 1, 6, 6 }, 434 435 { "%%xyz%Zd", "%xyz123", "123", 1, -1, -1 }, 436 { "12%%34%Zd", "12%34567", "567", 1, -1, -1 }, 437 { "%%%%%Zd", "%%123", "123", 1, -1, -1 }, 438 439 /* various subtle EOF cases */ 440 { "x", "", "-999", EOF, 0, -555 }, 441 { " x", "", "-999", EOF, 0, -555 }, 442 { "xyz", "", "-999", EOF, 0, -555 }, 443 { " ", "", "-999", 0, 0, 0 }, 444 { " ", " ", "-999", 0, 1, 1 }, 445 { "%*Zd%Zd", "", "-999", EOF, 0, -555 }, 446 { "%*Zd%Zd", "123", "-999", EOF, 3, -555 }, 447 { "x", "x", "-999", 0, 1, 1 }, 448 { "xyz", "x", "-999", EOF, 1, -555 }, 449 { "xyz", "xy", "-999", EOF, 2, -555 }, 450 { "xyz", "xyz", "-999", 0, 3, 3 }, 451 { "%Zn", "", "0", 0, 0, 0 }, 452 { " %Zn", "", "0", 0, 0, 0 }, 453 { " x%Zn", "", "-999", EOF, 0, -555 }, 454 { "xyz%Zn", "", "-999", EOF, 0, -555 }, 455 { " x%Zn", "", "-999", EOF, 0, -555 }, 456 { " %Zn x", " ", "-999", EOF, 1, -555 }, 457 458 /* these seem to tickle a bug in glibc 2.2.4 */ 459 { " x", " ", "-999", EOF, 1, -555, 1 }, 460 { " xyz", " ", "-999", EOF, 1, -555, 1 }, 461 { " x%Zn", " ", "-999", EOF, 1, -555, 1 }, 462 }; 463 464 int i, j, ignore; 465 int got_ret, want_ret, got_upto, want_upto; 466 mpz_t got, want; 467 long got_l, want_ftell; 468 int error = 0; 469 fun_t fun; 470 const char *name; 471 char fmt[128]; 472 473 mpz_init (got); 474 mpz_init (want); 475 476 for (i = 0; i < numberof (data); i++) 477 { 478 mpz_set_str_or_abort (want, data[i].want, 0); 479 480 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt)); 481 strcpy (fmt, data[i].fmt); 482 strcat (fmt, "%n"); 483 484 ignore = fmt_allignore (fmt); 485 486 for (j = 0; j <= 3; j++) 487 { 488 want_ret = data[i].want_ret; 489 490 want_ftell = data[i].want_ftell; 491 if (want_ftell == -1) 492 want_ftell = strlen (data[i].input); 493 494 want_upto = data[i].want_upto; 495 if (want_upto == -1) 496 want_upto = strlen (data[i].input); 497 498 switch (j) { 499 case 0: 500 name = "gmp_sscanf"; 501 fun = fun_gmp_sscanf; 502 break; 503 case 1: 504 name = "gmp_fscanf"; 505 fun = fun_gmp_fscanf; 506 break; 507 case 2: 508 #ifdef __GLIBC__ 509 if (data[i].not_glibc) 510 continue; 511 #endif 512 if (! libc_scanf_convert (fmt)) 513 continue; 514 name = "standard sscanf"; 515 fun = fun_sscanf; 516 break; 517 case 3: 518 #ifdef __GLIBC__ 519 if (data[i].not_glibc) 520 continue; 521 #endif 522 if (! libc_scanf_convert (fmt)) 523 continue; 524 name = "standard fscanf"; 525 fun = fun_fscanf; 526 break; 527 default: 528 ASSERT_ALWAYS (0); 529 break; 530 } 531 532 got_upto = -555; 533 got_ftell = -1L; 534 535 switch (j) { 536 case 0: 537 case 1: 538 mpz_set_si (got, -999L); 539 if (ignore) 540 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 541 else 542 got_ret = (*fun) (data[i].input, fmt, got, &got_upto); 543 break; 544 case 2: 545 case 3: 546 got_l = -999L; 547 if (ignore) 548 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 549 else 550 got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto); 551 mpz_set_si (got, got_l); 552 break; 553 default: 554 ASSERT_ALWAYS (0); 555 break; 556 } 557 558 MPZ_CHECK_FORMAT (got); 559 560 if (got_ret != want_ret) 561 { 562 printf ("%s wrong return value\n", name); 563 error = 1; 564 } 565 if (want_ret == 1 && mpz_cmp (want, got) != 0) 566 { 567 printf ("%s wrong result\n", name); 568 error = 1; 569 } 570 if (got_upto != want_upto) 571 { 572 printf ("%s wrong upto\n", name); 573 error = 1; 574 } 575 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell) 576 { 577 printf ("%s wrong ftell\n", name); 578 error = 1; 579 } 580 if (error) 581 { 582 printf (" fmt \"%s\"\n", data[i].fmt); 583 printf (" input \"%s\"\n", data[i].input); 584 printf (" ignore %d\n", ignore); 585 printf (" ret want=%d\n", want_ret); 586 printf (" got =%d\n", got_ret); 587 mpz_trace (" value want", want); 588 mpz_trace (" got ", got); 589 printf (" upto want =%d\n", want_upto); 590 printf (" got =%d\n", got_upto); 591 if (got_ftell != -1) 592 { 593 printf (" ftell want =%ld\n", want_ftell); 594 printf (" got =%ld\n", got_ftell); 595 } 596 abort (); 597 } 598 } 599 } 600 601 mpz_clear (got); 602 mpz_clear (want); 603 } 604 605 void 606 check_q (void) 607 { 608 static const struct { 609 const char *fmt; 610 const char *input; 611 const char *want; 612 int ret; 613 long ftell; 614 615 } data[] = { 616 617 { "%Qd", "0", "0", 1, -1 }, 618 { "%Qd", "1", "1", 1, -1 }, 619 { "%Qd", "123", "123", 1, -1 }, 620 { "%Qd", "+0", "0", 1, -1 }, 621 { "%Qd", "+1", "1", 1, -1 }, 622 { "%Qd", "+123", "123", 1, -1 }, 623 { "%Qd", "-0", "0", 1, -1 }, 624 { "%Qd", "-1", "-1", 1, -1 }, 625 { "%Qd", "-123", "-123", 1, -1 }, 626 627 { "%Qo", "0", "0", 1, -1 }, 628 { "%Qo", "173", "123", 1, -1 }, 629 { "%Qo", "+0", "0", 1, -1 }, 630 { "%Qo", "+173", "123", 1, -1 }, 631 { "%Qo", "-0", "0", 1, -1 }, 632 { "%Qo", "-173", "-123", 1, -1 }, 633 634 { "%Qx", "0", "0", 1, -1 }, 635 { "%Qx", "7b", "123", 1, -1 }, 636 { "%Qx", "7b", "123", 1, -1 }, 637 { "%Qx", "+0", "0", 1, -1 }, 638 { "%Qx", "+7b", "123", 1, -1 }, 639 { "%Qx", "+7b", "123", 1, -1 }, 640 { "%Qx", "-0", "-0", 1, -1 }, 641 { "%Qx", "-7b", "-123", 1, -1 }, 642 { "%Qx", "-7b", "-123", 1, -1 }, 643 { "%QX", "0", "0", 1, -1 }, 644 { "%QX", "7b", "123", 1, -1 }, 645 { "%QX", "7b", "123", 1, -1 }, 646 { "%QX", "+0", "0", 1, -1 }, 647 { "%QX", "+7b", "123", 1, -1 }, 648 { "%QX", "+7b", "123", 1, -1 }, 649 { "%QX", "-0", "-0", 1, -1 }, 650 { "%QX", "-7b", "-123", 1, -1 }, 651 { "%QX", "-7b", "-123", 1, -1 }, 652 { "%Qx", "0", "0", 1, -1 }, 653 { "%Qx", "7B", "123", 1, -1 }, 654 { "%Qx", "7B", "123", 1, -1 }, 655 { "%Qx", "+0", "0", 1, -1 }, 656 { "%Qx", "+7B", "123", 1, -1 }, 657 { "%Qx", "+7B", "123", 1, -1 }, 658 { "%Qx", "-0", "-0", 1, -1 }, 659 { "%Qx", "-7B", "-123", 1, -1 }, 660 { "%Qx", "-7B", "-123", 1, -1 }, 661 { "%QX", "0", "0", 1, -1 }, 662 { "%QX", "7B", "123", 1, -1 }, 663 { "%QX", "7B", "123", 1, -1 }, 664 { "%QX", "+0", "0", 1, -1 }, 665 { "%QX", "+7B", "123", 1, -1 }, 666 { "%QX", "+7B", "123", 1, -1 }, 667 { "%QX", "-0", "-0", 1, -1 }, 668 { "%QX", "-7B", "-123", 1, -1 }, 669 { "%QX", "-7B", "-123", 1, -1 }, 670 671 { "%Qi", "0", "0", 1, -1 }, 672 { "%Qi", "1", "1", 1, -1 }, 673 { "%Qi", "123", "123", 1, -1 }, 674 { "%Qi", "+0", "0", 1, -1 }, 675 { "%Qi", "+1", "1", 1, -1 }, 676 { "%Qi", "+123", "123", 1, -1 }, 677 { "%Qi", "-0", "0", 1, -1 }, 678 { "%Qi", "-1", "-1", 1, -1 }, 679 { "%Qi", "-123", "-123", 1, -1 }, 680 681 { "%Qi", "00", "0", 1, -1 }, 682 { "%Qi", "0173", "123", 1, -1 }, 683 { "%Qi", "+00", "0", 1, -1 }, 684 { "%Qi", "+0173", "123", 1, -1 }, 685 { "%Qi", "-00", "0", 1, -1 }, 686 { "%Qi", "-0173", "-123", 1, -1 }, 687 688 { "%Qi", "0x0", "0", 1, -1 }, 689 { "%Qi", "0x7b", "123", 1, -1 }, 690 { "%Qi", "0x7b", "123", 1, -1 }, 691 { "%Qi", "+0x0", "0", 1, -1 }, 692 { "%Qi", "+0x7b", "123", 1, -1 }, 693 { "%Qi", "+0x7b", "123", 1, -1 }, 694 { "%Qi", "-0x0", "-0", 1, -1 }, 695 { "%Qi", "-0x7b", "-123", 1, -1 }, 696 { "%Qi", "-0x7b", "-123", 1, -1 }, 697 { "%Qi", "0X0", "0", 1, -1 }, 698 { "%Qi", "0X7b", "123", 1, -1 }, 699 { "%Qi", "0X7b", "123", 1, -1 }, 700 { "%Qi", "+0X0", "0", 1, -1 }, 701 { "%Qi", "+0X7b", "123", 1, -1 }, 702 { "%Qi", "+0X7b", "123", 1, -1 }, 703 { "%Qi", "-0X0", "-0", 1, -1 }, 704 { "%Qi", "-0X7b", "-123", 1, -1 }, 705 { "%Qi", "-0X7b", "-123", 1, -1 }, 706 { "%Qi", "0x0", "0", 1, -1 }, 707 { "%Qi", "0x7B", "123", 1, -1 }, 708 { "%Qi", "0x7B", "123", 1, -1 }, 709 { "%Qi", "+0x0", "0", 1, -1 }, 710 { "%Qi", "+0x7B", "123", 1, -1 }, 711 { "%Qi", "+0x7B", "123", 1, -1 }, 712 { "%Qi", "-0x0", "-0", 1, -1 }, 713 { "%Qi", "-0x7B", "-123", 1, -1 }, 714 { "%Qi", "-0x7B", "-123", 1, -1 }, 715 { "%Qi", "0X0", "0", 1, -1 }, 716 { "%Qi", "0X7B", "123", 1, -1 }, 717 { "%Qi", "0X7B", "123", 1, -1 }, 718 { "%Qi", "+0X0", "0", 1, -1 }, 719 { "%Qi", "+0X7B", "123", 1, -1 }, 720 { "%Qi", "+0X7B", "123", 1, -1 }, 721 { "%Qi", "-0X0", "-0", 1, -1 }, 722 { "%Qi", "-0X7B", "-123", 1, -1 }, 723 { "%Qi", "-0X7B", "-123", 1, -1 }, 724 725 { "%Qd", " 0", "0", 1, -1 }, 726 { "%Qd", " 0", "0", 1, -1 }, 727 { "%Qd", " 0", "0", 1, -1 }, 728 { "%Qd", "\t0", "0", 1, -1 }, 729 { "%Qd", "\t\t0", "0", 1, -1 }, 730 731 { "%Qd", "3/2", "3/2", 1, -1 }, 732 { "%Qd", "+3/2", "3/2", 1, -1 }, 733 { "%Qd", "-3/2", "-3/2", 1, -1 }, 734 735 { "%Qx", "f/10", "15/16", 1, -1 }, 736 { "%Qx", "F/10", "15/16", 1, -1 }, 737 { "%QX", "f/10", "15/16", 1, -1 }, 738 { "%QX", "F/10", "15/16", 1, -1 }, 739 740 { "%Qo", "20/21", "16/17", 1, -1 }, 741 { "%Qo", "-20/21", "-16/17", 1, -1 }, 742 743 { "%Qi", "10/11", "10/11", 1, -1 }, 744 { "%Qi", "+10/11", "10/11", 1, -1 }, 745 { "%Qi", "-10/11", "-10/11", 1, -1 }, 746 { "%Qi", "010/11", "8/11", 1, -1 }, 747 { "%Qi", "+010/11", "8/11", 1, -1 }, 748 { "%Qi", "-010/11", "-8/11", 1, -1 }, 749 { "%Qi", "0x10/11", "16/11", 1, -1 }, 750 { "%Qi", "+0x10/11", "16/11", 1, -1 }, 751 { "%Qi", "-0x10/11", "-16/11", 1, -1 }, 752 753 { "%Qi", "10/011", "10/9", 1, -1 }, 754 { "%Qi", "+10/011", "10/9", 1, -1 }, 755 { "%Qi", "-10/011", "-10/9", 1, -1 }, 756 { "%Qi", "010/011", "8/9", 1, -1 }, 757 { "%Qi", "+010/011", "8/9", 1, -1 }, 758 { "%Qi", "-010/011", "-8/9", 1, -1 }, 759 { "%Qi", "0x10/011", "16/9", 1, -1 }, 760 { "%Qi", "+0x10/011", "16/9", 1, -1 }, 761 { "%Qi", "-0x10/011", "-16/9", 1, -1 }, 762 763 { "%Qi", "10/0x11", "10/17", 1, -1 }, 764 { "%Qi", "+10/0x11", "10/17", 1, -1 }, 765 { "%Qi", "-10/0x11", "-10/17", 1, -1 }, 766 { "%Qi", "010/0x11", "8/17", 1, -1 }, 767 { "%Qi", "+010/0x11", "8/17", 1, -1 }, 768 { "%Qi", "-010/0x11", "-8/17", 1, -1 }, 769 { "%Qi", "0x10/0x11", "16/17", 1, -1 }, 770 { "%Qi", "+0x10/0x11", "16/17", 1, -1 }, 771 { "%Qi", "-0x10/0x11", "-16/17", 1, -1 }, 772 773 { "hello%Qd", "hello0", "0", 1, -1 }, 774 { "hello%Qd", "hello 0", "0", 1, -1 }, 775 { "hello%Qd", "hello \t0", "0", 1, -1 }, 776 { "hello%Qdworld", "hello 0world", "0", 1, -1 }, 777 { "hello%Qd", "hello3/2", "3/2", 1, -1 }, 778 779 { "hello%*Qd", "hello0", "-999/121", 0, -1 }, 780 { "hello%*Qd", "hello 0", "-999/121", 0, -1 }, 781 { "hello%*Qd", "hello \t0", "-999/121", 0, -1 }, 782 { "hello%*Qdworld", "hello 0world", "-999/121", 0, -1 }, 783 { "hello%*Qdworld", "hello3/2world", "-999/121", 0, -1 }, 784 785 { "%Qd", "", "-999/121", -1, -1 }, 786 { "%Qd", " ", "-999/121", -1, -1 }, 787 { " %Qd", "", "-999/121", -1, -1 }, 788 { "xyz%Qd", "", "-999/121", -1, -1 }, 789 790 { "%*Qd", "", "-999/121", -1, -1 }, 791 { " %*Qd", "", "-999/121", -1, -1 }, 792 { "xyz%*Qd", "", "-999/121", -1, -1 }, 793 794 /* match something, but invalid */ 795 { "%Qd", "-", "-999/121", 0, 1 }, 796 { "%Qd", "+", "-999/121", 0, 1 }, 797 { "%Qd", "/-", "-999/121", 0, 1 }, 798 { "%Qd", "/+", "-999/121", 0, 1 }, 799 { "%Qd", "-/", "-999/121", 0, 1 }, 800 { "%Qd", "+/", "-999/121", 0, 1 }, 801 { "%Qd", "-/-", "-999/121", 0, 1 }, 802 { "%Qd", "-/+", "-999/121", 0, 1 }, 803 { "%Qd", "+/+", "-999/121", 0, 1 }, 804 { "%Qd", "/123", "-999/121", 0, 1 }, 805 { "%Qd", "-/123", "-999/121", 0, 1 }, 806 { "%Qd", "+/123", "-999/121", 0, 1 }, 807 { "%Qd", "123/", "-999/121", 0, 1 }, 808 { "%Qd", "123/-", "-999/121", 0, 1 }, 809 { "%Qd", "123/+", "-999/121", 0, 1 }, 810 { "xyz%Qd", "xyz-", "-999/121", 0, 4 }, 811 { "xyz%Qd", "xyz+", "-999/121", 0, 4 }, 812 813 { "%1Qi", "12/57", "1", 1, 1 }, 814 { "%2Qi", "12/57", "12", 1, 2 }, 815 { "%3Qi", "12/57", "-999/121", 0, -1 }, 816 { "%4Qi", "12/57", "12/5", 1, 4 }, 817 { "%5Qi", "12/57", "12/57", 1, 5 }, 818 { "%6Qi", "12/57", "12/57", 1, 5 }, 819 { "%7Qi", "12/57", "12/57", 1, 5 }, 820 821 { "%1Qi", "012/057", "0", 1, 1 }, 822 { "%2Qi", "012/057", "01", 1, 2 }, 823 { "%3Qi", "012/057", "012", 1, 3 }, 824 { "%4Qi", "012/057", "-999/121", 0, -1 }, 825 { "%5Qi", "012/057", "012/0", 1, 5 }, 826 { "%6Qi", "012/057", "012/5", 1, 6 }, 827 { "%7Qi", "012/057", "012/057", 1, 7 }, 828 { "%8Qi", "012/057", "012/057", 1, 7 }, 829 { "%9Qi", "012/057", "012/057", 1, 7 }, 830 831 { "%1Qi", "0x12/0x57", "0", 1, 1 }, 832 { "%2Qi", "0x12/0x57", "-999", 0, 2 }, 833 { "%3Qi", "0x12/0x57", "0x1", 1, 3 }, 834 { "%4Qi", "0x12/0x57", "0x12", 1, 4 }, 835 { "%5Qi", "0x12/0x57", "-999/121", 0, 5 }, 836 { "%6Qi", "0x12/0x57", "0x12/0", 1, 6 }, 837 { "%7Qi", "0x12/0x57", "-999/121", 0, 7 }, 838 { "%8Qi", "0x12/0x57", "0x12/0x5", 1, 8 }, 839 { "%9Qi", "0x12/0x57", "0x12/0x57", 1, 9 }, 840 { "%10Qi", "0x12/0x57", "0x12/0x57", 1, 9 }, 841 { "%11Qi", "0x12/0x57", "0x12/0x57", 1, 9 }, 842 843 { "%Qd", "xyz", "0", 0, 0 }, 844 }; 845 846 int i, j, ignore, got_ret, want_ret, got_upto, want_upto; 847 mpq_t got, want; 848 long got_l, want_ftell; 849 int error = 0; 850 fun_t fun; 851 const char *name; 852 char fmt[128]; 853 854 mpq_init (got); 855 mpq_init (want); 856 857 for (i = 0; i < numberof (data); i++) 858 { 859 mpq_set_str_or_abort (want, data[i].want, 0); 860 861 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt)); 862 strcpy (fmt, data[i].fmt); 863 strcat (fmt, "%n"); 864 865 ignore = (strchr (fmt, '*') != NULL); 866 867 for (j = 0; j <= 3; j++) 868 { 869 want_ret = data[i].ret; 870 871 want_ftell = data[i].ftell; 872 if (want_ftell == -1) 873 want_ftell = strlen (data[i].input); 874 want_upto = want_ftell; 875 876 if (want_ret == -1 || (want_ret == 0 && ! ignore)) 877 { 878 want_ftell = -1; 879 want_upto = -555; 880 } 881 882 switch (j) { 883 case 0: 884 name = "gmp_sscanf"; 885 fun = fun_gmp_sscanf; 886 break; 887 case 1: 888 name = "gmp_fscanf"; 889 fun = fun_gmp_fscanf; 890 break; 891 case 2: 892 if (strchr (data[i].input, '/') != NULL) 893 continue; 894 if (! libc_scanf_convert (fmt)) 895 continue; 896 name = "standard sscanf"; 897 fun = fun_sscanf; 898 break; 899 case 3: 900 if (strchr (data[i].input, '/') != NULL) 901 continue; 902 if (! libc_scanf_convert (fmt)) 903 continue; 904 name = "standard fscanf"; 905 fun = fun_fscanf; 906 break; 907 default: 908 ASSERT_ALWAYS (0); 909 break; 910 } 911 912 got_upto = -555; 913 got_ftell = -1; 914 915 switch (j) { 916 case 0: 917 case 1: 918 mpq_set_si (got, -999L, 121L); 919 if (ignore) 920 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 921 else 922 got_ret = (*fun) (data[i].input, fmt, got, &got_upto); 923 break; 924 case 2: 925 case 3: 926 got_l = -999L; 927 if (ignore) 928 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 929 else 930 got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto); 931 mpq_set_si (got, got_l, (got_l == -999L ? 121L : 1L)); 932 break; 933 default: 934 ASSERT_ALWAYS (0); 935 break; 936 } 937 938 MPZ_CHECK_FORMAT (mpq_numref (got)); 939 MPZ_CHECK_FORMAT (mpq_denref (got)); 940 941 if (got_ret != want_ret) 942 { 943 printf ("%s wrong return value\n", name); 944 error = 1; 945 } 946 /* use direct mpz compares, since some of the test data is 947 non-canonical and can trip ASSERTs in mpq_equal */ 948 if (want_ret == 1 949 && ! (mpz_cmp (mpq_numref(want), mpq_numref(got)) == 0 950 && mpz_cmp (mpq_denref(want), mpq_denref(got)) == 0)) 951 { 952 printf ("%s wrong result\n", name); 953 error = 1; 954 } 955 if (got_upto != want_upto) 956 { 957 printf ("%s wrong upto\n", name); 958 error = 1; 959 } 960 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell) 961 { 962 printf ("%s wrong ftell\n", name); 963 error = 1; 964 } 965 if (error) 966 { 967 printf (" fmt \"%s\"\n", data[i].fmt); 968 printf (" input \"%s\"\n", data[i].input); 969 printf (" ret want=%d\n", want_ret); 970 printf (" got =%d\n", got_ret); 971 mpq_trace (" value want", want); 972 mpq_trace (" got ", got); 973 printf (" upto want=%d\n", want_upto); 974 printf (" got =%d\n", got_upto); 975 if (got_ftell != -1) 976 { 977 printf (" ftell want =%ld\n", want_ftell); 978 printf (" got =%ld\n", got_ftell); 979 } 980 abort (); 981 } 982 } 983 } 984 985 mpq_clear (got); 986 mpq_clear (want); 987 } 988 989 void 990 check_f (void) 991 { 992 static const struct { 993 const char *fmt; 994 const char *input; 995 const char *want; 996 int ret; 997 long ftell; /* or -1 for length of input string */ 998 999 } data[] = { 1000 1001 { "%Ff", "0", "0", 1, -1 }, 1002 { "%Fe", "0", "0", 1, -1 }, 1003 { "%FE", "0", "0", 1, -1 }, 1004 { "%Fg", "0", "0", 1, -1 }, 1005 { "%FG", "0", "0", 1, -1 }, 1006 1007 { "%Ff", "123", "123", 1, -1 }, 1008 { "%Ff", "+123", "123", 1, -1 }, 1009 { "%Ff", "-123", "-123", 1, -1 }, 1010 { "%Ff", "123.", "123", 1, -1 }, 1011 { "%Ff", "+123.", "123", 1, -1 }, 1012 { "%Ff", "-123.", "-123", 1, -1 }, 1013 { "%Ff", "123.0", "123", 1, -1 }, 1014 { "%Ff", "+123.0", "123", 1, -1 }, 1015 { "%Ff", "-123.0", "-123", 1, -1 }, 1016 { "%Ff", "0123", "123", 1, -1 }, 1017 { "%Ff", "-0123", "-123", 1, -1 }, 1018 1019 { "%Ff", "123.456e3", "123456", 1, -1 }, 1020 { "%Ff", "-123.456e3", "-123456", 1, -1 }, 1021 { "%Ff", "123.456e+3", "123456", 1, -1 }, 1022 { "%Ff", "-123.456e+3", "-123456", 1, -1 }, 1023 { "%Ff", "123000e-3", "123", 1, -1 }, 1024 { "%Ff", "-123000e-3", "-123", 1, -1 }, 1025 { "%Ff", "123000.e-3", "123", 1, -1 }, 1026 { "%Ff", "-123000.e-3", "-123", 1, -1 }, 1027 1028 { "%Ff", "123.456E3", "123456", 1, -1 }, 1029 { "%Ff", "-123.456E3", "-123456", 1, -1 }, 1030 { "%Ff", "123.456E+3", "123456", 1, -1 }, 1031 { "%Ff", "-123.456E+3", "-123456", 1, -1 }, 1032 { "%Ff", "123000E-3", "123", 1, -1 }, 1033 { "%Ff", "-123000E-3", "-123", 1, -1 }, 1034 { "%Ff", "123000.E-3", "123", 1, -1 }, 1035 { "%Ff", "-123000.E-3", "-123", 1, -1 }, 1036 1037 { "%Ff", ".456e3", "456", 1, -1 }, 1038 { "%Ff", "-.456e3", "-456", 1, -1 }, 1039 { "%Ff", ".456e+3", "456", 1, -1 }, 1040 { "%Ff", "-.456e+3", "-456", 1, -1 }, 1041 1042 { "%Ff", " 0", "0", 1, -1 }, 1043 { "%Ff", " 0", "0", 1, -1 }, 1044 { "%Ff", " 0", "0", 1, -1 }, 1045 { "%Ff", "\t0", "0", 1, -1 }, 1046 { "%Ff", "\t\t0", "0", 1, -1 }, 1047 1048 { "hello%Fg", "hello0", "0", 1, -1 }, 1049 { "hello%Fg", "hello 0", "0", 1, -1 }, 1050 { "hello%Fg", "hello \t0", "0", 1, -1 }, 1051 { "hello%Fgworld", "hello 0world", "0", 1, -1 }, 1052 { "hello%Fg", "hello3.0", "3.0", 1, -1 }, 1053 1054 { "hello%*Fg", "hello0", "-999", 0, -1 }, 1055 { "hello%*Fg", "hello 0", "-999", 0, -1 }, 1056 { "hello%*Fg", "hello \t0", "-999", 0, -1 }, 1057 { "hello%*Fgworld", "hello 0world", "-999", 0, -1 }, 1058 { "hello%*Fgworld", "hello3.0world", "-999", 0, -1 }, 1059 1060 { "%Ff", "", "-999", -1, -1 }, 1061 { "%Ff", " ", "-999", -1, -1 }, 1062 { "%Ff", "\t", "-999", -1, -1 }, 1063 { "%Ff", " \t", "-999", -1, -1 }, 1064 { " %Ff", "", "-999", -1, -1 }, 1065 { "xyz%Ff", "", "-999", -1, -1 }, 1066 1067 { "%*Ff", "", "-999", -1, -1 }, 1068 { " %*Ff", "", "-999", -1, -1 }, 1069 { "xyz%*Ff", "", "-999", -1, -1 }, 1070 1071 { "%Ff", "xyz", "0", 0 }, 1072 1073 /* various non-empty but invalid */ 1074 { "%Ff", "-", "-999", 0, 1 }, 1075 { "%Ff", "+", "-999", 0, 1 }, 1076 { "xyz%Ff", "xyz-", "-999", 0, 4 }, 1077 { "xyz%Ff", "xyz+", "-999", 0, 4 }, 1078 { "%Ff", "-.", "-999", 0, 2 }, 1079 { "%Ff", "+.", "-999", 0, 2 }, 1080 { "%Ff", ".e", "-999", 0, 1 }, 1081 { "%Ff", "-.e", "-999", 0, 2 }, 1082 { "%Ff", "+.e", "-999", 0, 2 }, 1083 { "%Ff", ".E", "-999", 0, 1 }, 1084 { "%Ff", "-.E", "-999", 0, 2 }, 1085 { "%Ff", "+.E", "-999", 0, 2 }, 1086 { "%Ff", ".e123", "-999", 0, 1 }, 1087 { "%Ff", "-.e123", "-999", 0, 2 }, 1088 { "%Ff", "+.e123", "-999", 0, 2 }, 1089 { "%Ff", "123e", "-999", 0, 4 }, 1090 { "%Ff", "-123e", "-999", 0, 5 }, 1091 { "%Ff", "123e-", "-999", 0, 5 }, 1092 { "%Ff", "-123e-", "-999", 0, 6 }, 1093 { "%Ff", "123e+", "-999", 0, 5 }, 1094 { "%Ff", "-123e+", "-999", 0, 6 }, 1095 { "%Ff", "123e-Z", "-999", 0, 5 }, 1096 1097 /* hex floats */ 1098 { "%Ff", "0x123p0", "291", 1, -1 }, 1099 { "%Ff", "0x123P0", "291", 1, -1 }, 1100 { "%Ff", "0X123p0", "291", 1, -1 }, 1101 { "%Ff", "0X123P0", "291", 1, -1 }, 1102 { "%Ff", "-0x123p0", "-291", 1, -1 }, 1103 { "%Ff", "+0x123p0", "291", 1, -1 }, 1104 { "%Ff", "0x123.p0", "291", 1, -1 }, 1105 { "%Ff", "0x12.3p4", "291", 1, -1 }, 1106 { "%Ff", "-0x12.3p4", "-291", 1, -1 }, 1107 { "%Ff", "+0x12.3p4", "291", 1, -1 }, 1108 { "%Ff", "0x1230p-4", "291", 1, -1 }, 1109 { "%Ff", "-0x1230p-4", "-291", 1, -1 }, 1110 { "%Ff", "+0x1230p-4", "291", 1, -1 }, 1111 { "%Ff", "+0x.1230p12", "291", 1, -1 }, 1112 { "%Ff", "+0x123000p-12", "291", 1, -1 }, 1113 { "%Ff", "0x123 p12", "291", 1, 5 }, 1114 { "%Ff", "0x9 9", "9", 1, 3 }, 1115 { "%Ff", "0x01", "1", 1, 4 }, 1116 { "%Ff", "0x23", "35", 1, 4 }, 1117 { "%Ff", "0x45", "69", 1, 4 }, 1118 { "%Ff", "0x67", "103", 1, 4 }, 1119 { "%Ff", "0x89", "137", 1, 4 }, 1120 { "%Ff", "0xAB", "171", 1, 4 }, 1121 { "%Ff", "0xCD", "205", 1, 4 }, 1122 { "%Ff", "0xEF", "239", 1, 4 }, 1123 { "%Ff", "0xab", "171", 1, 4 }, 1124 { "%Ff", "0xcd", "205", 1, 4 }, 1125 { "%Ff", "0xef", "239", 1, 4 }, 1126 { "%Ff", "0x100p0A", "256", 1, 7 }, 1127 { "%Ff", "0x1p9", "512", 1, -1 }, 1128 1129 /* invalid hex floats */ 1130 { "%Ff", "0x", "-999", 0, 2 }, 1131 { "%Ff", "-0x", "-999", 0, 3 }, 1132 { "%Ff", "+0x", "-999", 0, 3 }, 1133 { "%Ff", "0x-", "-999", 0, 2 }, 1134 { "%Ff", "0x+", "-999", 0, 2 }, 1135 { "%Ff", "0x.", "-999", 0, 3 }, 1136 { "%Ff", "-0x.", "-999", 0, 4 }, 1137 { "%Ff", "+0x.", "-999", 0, 4 }, 1138 { "%Ff", "0x.p", "-999", 0, 3 }, 1139 { "%Ff", "-0x.p", "-999", 0, 4 }, 1140 { "%Ff", "+0x.p", "-999", 0, 4 }, 1141 { "%Ff", "0x.P", "-999", 0, 3 }, 1142 { "%Ff", "-0x.P", "-999", 0, 4 }, 1143 { "%Ff", "+0x.P", "-999", 0, 4 }, 1144 { "%Ff", ".p123", "-999", 0, 1 }, 1145 { "%Ff", "-.p123", "-999", 0, 2 }, 1146 { "%Ff", "+.p123", "-999", 0, 2 }, 1147 { "%Ff", "0x1p", "-999", 0, 4 }, 1148 { "%Ff", "0x1p-", "-999", 0, 5 }, 1149 { "%Ff", "0x1p+", "-999", 0, 5 }, 1150 { "%Ff", "0x123p 12", "291", 0, 6 }, 1151 { "%Ff", "0x 123p12", "291", 0, 2 }, 1152 1153 }; 1154 1155 int i, j, ignore, got_ret, want_ret, got_upto, want_upto; 1156 mpf_t got, want; 1157 double got_d; 1158 long want_ftell; 1159 int error = 0; 1160 fun_t fun; 1161 const char *name; 1162 char fmt[128]; 1163 1164 mpf_init (got); 1165 mpf_init (want); 1166 1167 for (i = 0; i < numberof (data); i++) 1168 { 1169 mpf_set_str_or_abort (want, data[i].want, 10); 1170 1171 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt)); 1172 strcpy (fmt, data[i].fmt); 1173 strcat (fmt, "%n"); 1174 1175 ignore = (strchr (fmt, '*') != NULL); 1176 1177 for (j = 0; j <= 3; j++) 1178 { 1179 want_ret = data[i].ret; 1180 1181 want_ftell = data[i].ftell; 1182 if (want_ftell == -1) 1183 want_ftell = strlen (data[i].input); 1184 want_upto = want_ftell; 1185 1186 if (want_ret == -1 || (want_ret == 0 && ! ignore)) 1187 want_upto = -555; 1188 1189 switch (j) { 1190 case 0: 1191 name = "gmp_sscanf"; 1192 fun = fun_gmp_sscanf; 1193 break; 1194 case 1: 1195 name = "gmp_fscanf"; 1196 fun = fun_gmp_fscanf; 1197 break; 1198 case 2: 1199 if (! libc_scanf_convert (fmt)) 1200 continue; 1201 name = "standard sscanf"; 1202 fun = fun_sscanf; 1203 break; 1204 case 3: 1205 if (! libc_scanf_convert (fmt)) 1206 continue; 1207 name = "standard fscanf"; 1208 fun = fun_fscanf; 1209 break; 1210 default: 1211 ASSERT_ALWAYS (0); 1212 break; 1213 } 1214 1215 got_upto = -555; 1216 got_ftell = -1; 1217 1218 switch (j) { 1219 case 0: 1220 case 1: 1221 mpf_set_si (got, -999L); 1222 if (ignore) 1223 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 1224 else 1225 got_ret = (*fun) (data[i].input, fmt, got, &got_upto); 1226 break; 1227 case 2: 1228 case 3: 1229 got_d = -999L; 1230 if (ignore) 1231 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL); 1232 else 1233 got_ret = (*fun) (data[i].input, fmt, &got_d, &got_upto); 1234 mpf_set_d (got, got_d); 1235 break; 1236 default: 1237 ASSERT_ALWAYS (0); 1238 break; 1239 } 1240 1241 MPF_CHECK_FORMAT (got); 1242 1243 if (got_ret != want_ret) 1244 { 1245 printf ("%s wrong return value\n", name); 1246 error = 1; 1247 } 1248 if (want_ret == 1 && mpf_cmp (want, got) != 0) 1249 { 1250 printf ("%s wrong result\n", name); 1251 error = 1; 1252 } 1253 if (got_upto != want_upto) 1254 { 1255 printf ("%s wrong upto\n", name); 1256 error = 1; 1257 } 1258 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell) 1259 { 1260 printf ("%s wrong ftell\n", name); 1261 error = 1; 1262 } 1263 if (error) 1264 { 1265 printf (" fmt \"%s\"\n", data[i].fmt); 1266 printf (" input \"%s\"\n", data[i].input); 1267 printf (" ret want=%d\n", want_ret); 1268 printf (" got =%d\n", got_ret); 1269 mpf_trace (" value want", want); 1270 mpf_trace (" got ", got); 1271 printf (" upto want=%d\n", want_upto); 1272 printf (" got =%d\n", got_upto); 1273 if (got_ftell != -1) 1274 { 1275 printf (" ftell want =%ld\n", want_ftell); 1276 printf (" got =%ld\n", got_ftell); 1277 } 1278 abort (); 1279 } 1280 } 1281 } 1282 1283 mpf_clear (got); 1284 mpf_clear (want); 1285 } 1286 1287 1288 void 1289 check_n (void) 1290 { 1291 int ret; 1292 1293 /* %n suppressed */ 1294 { 1295 int n = 123; 1296 gmp_sscanf (" ", " %*n", &n); 1297 ASSERT_ALWAYS (n == 123); 1298 } 1299 { 1300 int n = 123; 1301 fromstring_gmp_fscanf (" ", " %*n", &n); 1302 ASSERT_ALWAYS (n == 123); 1303 } 1304 1305 1306 #define CHECK_N(type, string) \ 1307 do { \ 1308 type x[2]; \ 1309 char fmt[128]; \ 1310 int ret; \ 1311 \ 1312 x[0] = ~ (type) 0; \ 1313 x[1] = ~ (type) 0; \ 1314 sprintf (fmt, "abc%%%sn", string); \ 1315 ret = gmp_sscanf ("abc", fmt, &x[0]); \ 1316 \ 1317 ASSERT_ALWAYS (ret == 0); \ 1318 \ 1319 /* should write whole of x[0] and none of x[1] */ \ 1320 ASSERT_ALWAYS (x[0] == 3); \ 1321 ASSERT_ALWAYS (x[1] == (type) ~ (type) 0); \ 1322 \ 1323 } while (0) 1324 1325 CHECK_N (char, "hh"); 1326 CHECK_N (long, "l"); 1327 #if HAVE_LONG_LONG 1328 CHECK_N (long long, "L"); 1329 #endif 1330 #if HAVE_INTMAX_T 1331 CHECK_N (intmax_t, "j"); 1332 #endif 1333 #if HAVE_PTRDIFF_T 1334 CHECK_N (ptrdiff_t, "t"); 1335 #endif 1336 CHECK_N (short, "h"); 1337 CHECK_N (size_t, "z"); 1338 1339 /* %Zn */ 1340 { 1341 mpz_t x[2]; 1342 mpz_init_set_si (x[0], -987L); 1343 mpz_init_set_si (x[1], 654L); 1344 ret = gmp_sscanf ("xyz ", "xyz%Zn", x[0]); 1345 MPZ_CHECK_FORMAT (x[0]); 1346 MPZ_CHECK_FORMAT (x[1]); 1347 ASSERT_ALWAYS (ret == 0); 1348 ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0); 1349 ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0); 1350 mpz_clear (x[0]); 1351 mpz_clear (x[1]); 1352 } 1353 { 1354 mpz_t x; 1355 mpz_init (x); 1356 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Zn", x); 1357 ASSERT_ALWAYS (ret == 0); 1358 ASSERT_ALWAYS (mpz_cmp_ui (x, 3L) == 0); 1359 mpz_clear (x); 1360 } 1361 1362 /* %Qn */ 1363 { 1364 mpq_t x[2]; 1365 mpq_init (x[0]); 1366 mpq_init (x[1]); 1367 mpq_set_ui (x[0], 987L, 654L); 1368 mpq_set_ui (x[1], 4115L, 226L); 1369 ret = gmp_sscanf ("xyz ", "xyz%Qn", x[0]); 1370 MPQ_CHECK_FORMAT (x[0]); 1371 MPQ_CHECK_FORMAT (x[1]); 1372 ASSERT_ALWAYS (ret == 0); 1373 ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0); 1374 ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0); 1375 mpq_clear (x[0]); 1376 mpq_clear (x[1]); 1377 } 1378 { 1379 mpq_t x; 1380 mpq_init (x); 1381 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Qn", x); 1382 ASSERT_ALWAYS (ret == 0); 1383 ASSERT_ALWAYS (mpq_cmp_ui (x, 3L, 1L) == 0); 1384 mpq_clear (x); 1385 } 1386 1387 /* %Fn */ 1388 { 1389 mpf_t x[2]; 1390 mpf_init (x[0]); 1391 mpf_init (x[1]); 1392 mpf_set_ui (x[0], 987L); 1393 mpf_set_ui (x[1], 654L); 1394 ret = gmp_sscanf ("xyz ", "xyz%Fn", x[0]); 1395 MPF_CHECK_FORMAT (x[0]); 1396 MPF_CHECK_FORMAT (x[1]); 1397 ASSERT_ALWAYS (ret == 0); 1398 ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0); 1399 ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0); 1400 mpf_clear (x[0]); 1401 mpf_clear (x[1]); 1402 } 1403 { 1404 mpf_t x; 1405 mpf_init (x); 1406 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Fn", x); 1407 ASSERT_ALWAYS (ret == 0); 1408 ASSERT_ALWAYS (mpf_cmp_ui (x, 3L) == 0); 1409 mpf_clear (x); 1410 } 1411 } 1412 1413 1414 void 1415 check_misc (void) 1416 { 1417 int ret, cmp; 1418 { 1419 int a=9, b=8, c=7, n=66; 1420 mpz_t z; 1421 mpz_init (z); 1422 ret = gmp_sscanf ("1 2 3 4", "%d %d %d %Zd%n", 1423 &a, &b, &c, z, &n); 1424 ASSERT_ALWAYS (ret == 4); 1425 ASSERT_ALWAYS (a == 1); 1426 ASSERT_ALWAYS (b == 2); 1427 ASSERT_ALWAYS (c == 3); 1428 ASSERT_ALWAYS (n == 7); 1429 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0); 1430 mpz_clear (z); 1431 } 1432 { 1433 int a=9, b=8, c=7, n=66; 1434 mpz_t z; 1435 mpz_init (z); 1436 ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %d %d %Zd%n", 1437 &a, &b, &c, z, &n); 1438 ASSERT_ALWAYS (ret == 4); 1439 ASSERT_ALWAYS (a == 1); 1440 ASSERT_ALWAYS (b == 2); 1441 ASSERT_ALWAYS (c == 3); 1442 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0); 1443 ASSERT_ALWAYS (n == 7); 1444 ASSERT_ALWAYS (got_ftell == 7); 1445 mpz_clear (z); 1446 } 1447 1448 { 1449 int a=9, n=8; 1450 mpz_t z; 1451 mpz_init (z); 1452 ret = gmp_sscanf ("1 2 3 4", "%d %*d %*d %Zd%n", &a, z, &n); 1453 ASSERT_ALWAYS (ret == 2); 1454 ASSERT_ALWAYS (a == 1); 1455 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0); 1456 ASSERT_ALWAYS (n == 7); 1457 mpz_clear (z); 1458 } 1459 { 1460 int a=9, n=8; 1461 mpz_t z; 1462 mpz_init (z); 1463 ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %*d %*d %Zd%n", 1464 &a, z, &n); 1465 ASSERT_ALWAYS (ret == 2); 1466 ASSERT_ALWAYS (a == 1); 1467 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0); 1468 ASSERT_ALWAYS (n == 7); 1469 ASSERT_ALWAYS (got_ftell == 7); 1470 mpz_clear (z); 1471 } 1472 1473 /* EOF for no matching */ 1474 { 1475 char buf[128]; 1476 ret = gmp_sscanf (" ", "%s", buf); 1477 ASSERT_ALWAYS (ret == EOF); 1478 ret = fromstring_gmp_fscanf (" ", "%s", buf); 1479 ASSERT_ALWAYS (ret == EOF); 1480 if (option_libc_scanf) 1481 { 1482 ret = sscanf (" ", "%s", buf); 1483 ASSERT_ALWAYS (ret == EOF); 1484 ret = fun_fscanf (" ", "%s", buf, NULL); 1485 ASSERT_ALWAYS (ret == EOF); 1486 } 1487 } 1488 1489 /* suppressed field, then eof */ 1490 { 1491 int x; 1492 if (test_sscanf_eof_ok ()) 1493 { 1494 ret = gmp_sscanf ("123", "%*d%d", &x); 1495 ASSERT_ALWAYS (ret == EOF); 1496 } 1497 ret = fromstring_gmp_fscanf ("123", "%*d%d", &x); 1498 ASSERT_ALWAYS (ret == EOF); 1499 if (option_libc_scanf) 1500 { 1501 ret = sscanf ("123", "%*d%d", &x); 1502 ASSERT_ALWAYS (ret == EOF); 1503 ret = fun_fscanf ("123", "%*d%d", &x, NULL); 1504 ASSERT_ALWAYS (ret == EOF); 1505 } 1506 } 1507 { 1508 mpz_t x; 1509 mpz_init (x); 1510 ret = gmp_sscanf ("123", "%*Zd%Zd", x); 1511 ASSERT_ALWAYS (ret == EOF); 1512 ret = fromstring_gmp_fscanf ("123", "%*Zd%Zd", x); 1513 ASSERT_ALWAYS (ret == EOF); 1514 mpz_clear (x); 1515 } 1516 1517 /* %[...], glibc only */ 1518 #ifdef __GLIBC__ 1519 { 1520 char buf[128]; 1521 int n = -1; 1522 buf[0] = '\0'; 1523 ret = gmp_sscanf ("abcdefgh", "%[a-d]ef%n", buf, &n); 1524 ASSERT_ALWAYS (ret == 1); 1525 cmp = strcmp (buf, "abcd"); 1526 ASSERT_ALWAYS (cmp == 0); 1527 ASSERT_ALWAYS (n == 6); 1528 } 1529 { 1530 char buf[128]; 1531 int n = -1; 1532 buf[0] = '\0'; 1533 ret = gmp_sscanf ("xyza", "%[^a]a%n", buf, &n); 1534 ASSERT_ALWAYS (ret == 1); 1535 cmp = strcmp (buf, "xyz"); 1536 ASSERT_ALWAYS (cmp == 0); 1537 ASSERT_ALWAYS (n == 4); 1538 } 1539 { 1540 char buf[128]; 1541 int n = -1; 1542 buf[0] = '\0'; 1543 ret = gmp_sscanf ("ab]ab]", "%[]ab]%n", buf, &n); 1544 ASSERT_ALWAYS (ret == 1); 1545 cmp = strcmp (buf, "ab]ab]"); 1546 ASSERT_ALWAYS (cmp == 0); 1547 ASSERT_ALWAYS (n == 6); 1548 } 1549 { 1550 char buf[128]; 1551 int n = -1; 1552 buf[0] = '\0'; 1553 ret = gmp_sscanf ("xyzb", "%[^]ab]b%n", buf, &n); 1554 ASSERT_ALWAYS (ret == 1); 1555 cmp = strcmp (buf, "xyz"); 1556 ASSERT_ALWAYS (cmp == 0); 1557 ASSERT_ALWAYS (n == 4); 1558 } 1559 #endif 1560 1561 /* %zd etc won't be accepted by sscanf on old systems, and running 1562 something to see if they work might be bad, so only try it on glibc, 1563 and only on a new enough version (glibc 2.0 doesn't have %zd) */ 1564 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0) 1565 { 1566 mpz_t z; 1567 size_t s = -1; 1568 mpz_init (z); 1569 ret = gmp_sscanf ("456 789", "%zd %Zd", &s, z); 1570 ASSERT_ALWAYS (ret == 2); 1571 ASSERT_ALWAYS (s == 456); 1572 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0); 1573 mpz_clear (z); 1574 } 1575 { 1576 mpz_t z; 1577 ptrdiff_t d = -1; 1578 mpz_init (z); 1579 ret = gmp_sscanf ("456 789", "%td %Zd", &d, z); 1580 ASSERT_ALWAYS (ret == 2); 1581 ASSERT_ALWAYS (d == 456); 1582 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0); 1583 mpz_clear (z); 1584 } 1585 { 1586 mpz_t z; 1587 long long ll = -1; 1588 mpz_init (z); 1589 ret = gmp_sscanf ("456 789", "%Ld %Zd", &ll, z); 1590 ASSERT_ALWAYS (ret == 2); 1591 ASSERT_ALWAYS (ll == 456); 1592 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0); 1593 mpz_clear (z); 1594 } 1595 #endif 1596 } 1597 1598 int 1599 main (int argc, char *argv[]) 1600 { 1601 if (argc > 1 && strcmp (argv[1], "-s") == 0) 1602 option_libc_scanf = 1; 1603 1604 tests_start (); 1605 1606 mp_trace_base = 16; 1607 1608 check_z (); 1609 check_q (); 1610 check_f (); 1611 check_n (); 1612 check_misc (); 1613 1614 unlink (TEMPFILE); 1615 tests_end (); 1616 exit (0); 1617 }