1 /* Test gmp_scanf and related functions.
3 Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 /* Usage: t-scanf [-s]
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
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. */
40 #include <stddef.h> /* for ptrdiff_t */
46 # include <inttypes.h> /* for intmax_t */
54 #include <unistd.h> /* for unlink */
62 #define TEMPFILE "t-scanf.tmp"
64 int option_libc_scanf = 0;
66 typedef int (*fun_t) __GMP_PROTO ((const char *, const char *, void *, void *));
69 /* This problem was seen on powerpc7450-apple-darwin7.0.0, sscanf returns 0
70 where it should return EOF. A workaround in gmp_sscanf would be a bit
71 tedious, and since this is a rather obvious libc bug, quite likely
72 affecting other programs, we'll just suppress affected tests for now. */
74 test_sscanf_eof_ok (void)
76 static int result = -1;
81 if (sscanf ("", "%d", &x) == EOF)
87 printf ("Warning, sscanf(\"\",\"%%d\",&x) doesn't return EOF.\n");
88 printf ("This affects gmp_sscanf, tests involving it will be suppressed.\n");
89 printf ("You should try to get a fix for your libc.\n");
97 /* Convert fmt from a GMP scanf format string to an equivalent for a plain
98 libc scanf, for example "%Zd" becomes "%ld". Return 1 if this succeeds,
99 0 if it cannot (or should not) be done. */
101 libc_scanf_convert (char *fmt)
105 if (! option_libc_scanf)
108 for ( ; *fmt != '\0'; fmt++)
128 int fromstring_next_c;
130 /* Call gmp_fscanf, reading the "input" string data provided. */
133 fromstring_gmp_fscanf (const char *input, const char *fmt, ...)
135 fromstring_gmp_fscanf (va_alist)
148 input = va_arg (ap, const char *);
149 fmt = va_arg (ap, const char *);
152 fp = fopen (TEMPFILE, "w+");
153 ASSERT_ALWAYS (fp != NULL);
154 ASSERT_ALWAYS (fputs (input, fp) != EOF);
155 ASSERT_ALWAYS (fflush (fp) == 0);
158 ret = gmp_vfscanf (fp, fmt, ap);
159 got_ftell = ftell (fp);
160 ASSERT_ALWAYS (got_ftell != -1L);
162 fromstring_next_c = getc (fp);
164 ASSERT_ALWAYS (fclose (fp) == 0);
171 fun_gmp_sscanf (const char *input, const char *fmt, void *a1, void *a2)
174 return gmp_sscanf (input, fmt, a1);
176 return gmp_sscanf (input, fmt, a1, a2);
180 fun_gmp_fscanf (const char *input, const char *fmt, void *a1, void *a2)
183 return fromstring_gmp_fscanf (input, fmt, a1);
185 return fromstring_gmp_fscanf (input, fmt, a1, a2);
190 fun_fscanf (const char *input, const char *fmt, void *a1, void *a2)
195 fp = fopen (TEMPFILE, "w+");
196 ASSERT_ALWAYS (fp != NULL);
197 ASSERT_ALWAYS (fputs (input, fp) != EOF);
198 ASSERT_ALWAYS (fflush (fp) == 0);
202 ret = fscanf (fp, fmt, a1);
204 ret = fscanf (fp, fmt, a1, a2);
206 got_ftell = ftell (fp);
207 ASSERT_ALWAYS (got_ftell != -1L);
209 fromstring_next_c = getc (fp);
211 ASSERT_ALWAYS (fclose (fp) == 0);
216 /* On various old systems, for instance HP-UX 9, the C library sscanf needs
217 to be able to write into the input string. Ensure that this is possible,
218 when gcc is putting the test data into a read-only section.
220 Actually we ought to only need this under SSCANF_WRITABLE_INPUT from
221 configure, but it's just as easy to do it unconditionally, and in any
222 case this code is only executed under the -s option. */
225 fun_sscanf (const char *input, const char *fmt, void *a1, void *a2)
227 char *input_writable;
231 size = strlen (input) + 1;
232 input_writable = (*__gmp_allocate_func) (size);
233 memcpy (input_writable, input, size);
236 ret = sscanf (input_writable, fmt, a1);
238 ret = sscanf (input_writable, fmt, a1, a2);
240 (*__gmp_free_func) (input_writable, size);
245 /* whether the format string consists entirely of ignored fields */
247 fmt_allignore (const char *fmt)
250 for ( ; *fmt != '\0'; fmt++)
269 static const struct {
280 { "%Zd", "0", "0", 1, -1, -1 },
281 { "%Zd", "1", "1", 1, -1, -1 },
282 { "%Zd", "123", "123", 1, -1, -1 },
283 { "%Zd", "+0", "0", 1, -1, -1 },
284 { "%Zd", "+1", "1", 1, -1, -1 },
285 { "%Zd", "+123", "123", 1, -1, -1 },
286 { "%Zd", "-0", "0", 1, -1, -1 },
287 { "%Zd", "-1", "-1", 1, -1, -1 },
288 { "%Zd", "-123", "-123", 1, -1, -1 },
290 { "%Zo", "0", "0", 1, -1, -1 },
291 { "%Zo", "173", "123", 1, -1, -1 },
292 { "%Zo", "+0", "0", 1, -1, -1 },
293 { "%Zo", "+173", "123", 1, -1, -1 },
294 { "%Zo", "-0", "0", 1, -1, -1 },
295 { "%Zo", "-173", "-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 { "%Zx", "0", "0", 1, -1, -1 },
316 { "%Zx", "7B", "123", 1, -1, -1 },
317 { "%Zx", "7B", "123", 1, -1, -1 },
318 { "%Zx", "+0", "0", 1, -1, -1 },
319 { "%Zx", "+7B", "123", 1, -1, -1 },
320 { "%Zx", "+7B", "123", 1, -1, -1 },
321 { "%Zx", "-0", "-0", 1, -1, -1 },
322 { "%Zx", "-7B", "-123", 1, -1, -1 },
323 { "%Zx", "-7B", "-123", 1, -1, -1 },
324 { "%ZX", "0", "0", 1, -1, -1 },
325 { "%ZX", "7B", "123", 1, -1, -1 },
326 { "%ZX", "7B", "123", 1, -1, -1 },
327 { "%ZX", "+0", "0", 1, -1, -1 },
328 { "%ZX", "+7B", "123", 1, -1, -1 },
329 { "%ZX", "+7B", "123", 1, -1, -1 },
330 { "%ZX", "-0", "-0", 1, -1, -1 },
331 { "%ZX", "-7B", "-123", 1, -1, -1 },
332 { "%ZX", "-7B", "-123", 1, -1, -1 },
334 { "%Zi", "0", "0", 1, -1, -1 },
335 { "%Zi", "1", "1", 1, -1, -1 },
336 { "%Zi", "123", "123", 1, -1, -1 },
337 { "%Zi", "+0", "0", 1, -1, -1 },
338 { "%Zi", "+1", "1", 1, -1, -1 },
339 { "%Zi", "+123", "123", 1, -1, -1 },
340 { "%Zi", "-0", "0", 1, -1, -1 },
341 { "%Zi", "-1", "-1", 1, -1, -1 },
342 { "%Zi", "-123", "-123", 1, -1, -1 },
344 { "%Zi", "00", "0", 1, -1, -1 },
345 { "%Zi", "0173", "123", 1, -1, -1 },
346 { "%Zi", "+00", "0", 1, -1, -1 },
347 { "%Zi", "+0173", "123", 1, -1, -1 },
348 { "%Zi", "-00", "0", 1, -1, -1 },
349 { "%Zi", "-0173", "-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 { "%Zi", "0x0", "0", 1, -1, -1 },
370 { "%Zi", "0x7B", "123", 1, -1, -1 },
371 { "%Zi", "0x7B", "123", 1, -1, -1 },
372 { "%Zi", "+0x0", "0", 1, -1, -1 },
373 { "%Zi", "+0x7B", "123", 1, -1, -1 },
374 { "%Zi", "+0x7B", "123", 1, -1, -1 },
375 { "%Zi", "-0x0", "-0", 1, -1, -1 },
376 { "%Zi", "-0x7B", "-123", 1, -1, -1 },
377 { "%Zi", "-0x7B", "-123", 1, -1, -1 },
378 { "%Zi", "0X0", "0", 1, -1, -1 },
379 { "%Zi", "0X7B", "123", 1, -1, -1 },
380 { "%Zi", "0X7B", "123", 1, -1, -1 },
381 { "%Zi", "+0X0", "0", 1, -1, -1 },
382 { "%Zi", "+0X7B", "123", 1, -1, -1 },
383 { "%Zi", "+0X7B", "123", 1, -1, -1 },
384 { "%Zi", "-0X0", "-0", 1, -1, -1 },
385 { "%Zi", "-0X7B", "-123", 1, -1, -1 },
386 { "%Zi", "-0X7B", "-123", 1, -1, -1 },
388 { "%Zd", " 0", "0", 1, -1, -1 },
389 { "%Zd", " 0", "0", 1, -1, -1 },
390 { "%Zd", " 0", "0", 1, -1, -1 },
391 { "%Zd", "\t0", "0", 1, -1, -1 },
392 { "%Zd", "\t\t0", "0", 1, -1, -1 },
394 { "hello%Zd", "hello0", "0", 1, -1, -1 },
395 { "hello%Zd", "hello 0", "0", 1, -1, -1 },
396 { "hello%Zd", "hello \t0", "0", 1, -1, -1 },
397 { "hello%Zdworld", "hello 0world", "0", 1, -1, -1 },
399 { "hello%*Zd", "hello0", "-999", 0, -1, -1 },
400 { "hello%*Zd", "hello 0", "-999", 0, -1, -1 },
401 { "hello%*Zd", "hello \t0", "-999", 0, -1, -1 },
402 { "hello%*Zdworld", "hello 0world", "-999", 0, -1, -1 },
404 { "%Zd", "", "-999", -1, -1, -555 },
405 { "%Zd", " ", "-999", -1, -1, -555 },
406 { " %Zd", "", "-999", -1, -1, -555 },
407 { "xyz%Zd", "", "-999", -1, -1, -555 },
409 { "%*Zd", "", "-999", -1, -1, -555 },
410 { " %*Zd", "", "-999", -1, -1, -555 },
411 { "xyz%*Zd", "", "-999", -1, -1, -555 },
413 { "%Zd", "xyz", "0", 0, 0, -555 },
415 /* match something, but invalid */
416 { "%Zd", "-", "-999", 0, 1, -555 },
417 { "%Zd", "+", "-999", 0, 1, -555 },
418 { "xyz%Zd", "xyz-", "-999", 0, 4, -555 },
419 { "xyz%Zd", "xyz+", "-999", 0, 4, -555 },
420 { "%Zi", "0x", "-999", 0, 2, -555 },
421 { "%Zi", "0X", "-999", 0, 2, -555 },
422 { "%Zi", "0x-", "-999", 0, 2, -555 },
423 { "%Zi", "0X+", "-999", 0, 2, -555 },
424 { "%Zi", "-0x", "-999", 0, 3, -555 },
425 { "%Zi", "-0X", "-999", 0, 3, -555 },
426 { "%Zi", "+0x", "-999", 0, 3, -555 },
427 { "%Zi", "+0X", "-999", 0, 3, -555 },
429 { "%1Zi", "1234", "1", 1, 1, 1 },
430 { "%2Zi", "1234", "12", 1, 2, 2 },
431 { "%3Zi", "1234", "123", 1, 3, 3 },
432 { "%4Zi", "1234", "1234", 1, 4, 4 },
433 { "%5Zi", "1234", "1234", 1, 4, 4 },
434 { "%6Zi", "1234", "1234", 1, 4, 4 },
436 { "%1Zi", "01234", "0", 1, 1, 1 },
437 { "%2Zi", "01234", "01", 1, 2, 2 },
438 { "%3Zi", "01234", "012", 1, 3, 3 },
439 { "%4Zi", "01234", "0123", 1, 4, 4 },
440 { "%5Zi", "01234", "01234", 1, 5, 5 },
441 { "%6Zi", "01234", "01234", 1, 5, 5 },
442 { "%7Zi", "01234", "01234", 1, 5, 5 },
444 { "%1Zi", "0x1234", "0", 1, 1, 1 },
445 { "%2Zi", "0x1234", "-999", 0, 2, -555 },
446 { "%3Zi", "0x1234", "0x1", 1, 3, 3 },
447 { "%4Zi", "0x1234", "0x12", 1, 4, 4 },
448 { "%5Zi", "0x1234", "0x123", 1, 5, 5 },
449 { "%6Zi", "0x1234", "0x1234", 1, 6, 6 },
450 { "%7Zi", "0x1234", "0x1234", 1, 6, 6 },
451 { "%8Zi", "0x1234", "0x1234", 1, 6, 6 },
453 { "%%xyz%Zd", "%xyz123", "123", 1, -1, -1 },
454 { "12%%34%Zd", "12%34567", "567", 1, -1, -1 },
455 { "%%%%%Zd", "%%123", "123", 1, -1, -1 },
457 /* various subtle EOF cases */
458 { "x", "", "-999", EOF, 0, -555 },
459 { " x", "", "-999", EOF, 0, -555 },
460 { "xyz", "", "-999", EOF, 0, -555 },
461 { " ", "", "-999", 0, 0, 0 },
462 { " ", " ", "-999", 0, 1, 1 },
463 { "%*Zd%Zd", "", "-999", EOF, 0, -555 },
464 { "%*Zd%Zd", "123", "-999", EOF, 3, -555 },
465 { "x", "x", "-999", 0, 1, 1 },
466 { "xyz", "x", "-999", EOF, 1, -555 },
467 { "xyz", "xy", "-999", EOF, 2, -555 },
468 { "xyz", "xyz", "-999", 0, 3, 3 },
469 { "%Zn", "", "0", 0, 0, 0 },
470 { " %Zn", "", "0", 0, 0, 0 },
471 { " x%Zn", "", "-999", EOF, 0, -555 },
472 { "xyz%Zn", "", "-999", EOF, 0, -555 },
473 { " x%Zn", "", "-999", EOF, 0, -555 },
474 { " %Zn x", " ", "-999", EOF, 1, -555 },
476 /* these seem to tickle a bug in glibc 2.2.4 */
477 { " x", " ", "-999", EOF, 1, -555, 1 },
478 { " xyz", " ", "-999", EOF, 1, -555, 1 },
479 { " x%Zn", " ", "-999", EOF, 1, -555, 1 },
483 int got_ret, want_ret, got_upto, want_upto;
485 long got_l, want_ftell;
494 for (i = 0; i < numberof (data); i++)
496 mpz_set_str_or_abort (want, data[i].want, 0);
498 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
499 strcpy (fmt, data[i].fmt);
502 ignore = fmt_allignore (fmt);
504 for (j = 0; j <= 3; j++)
506 want_ret = data[i].want_ret;
508 want_ftell = data[i].want_ftell;
509 if (want_ftell == -1)
510 want_ftell = strlen (data[i].input);
512 want_upto = data[i].want_upto;
514 want_upto = strlen (data[i].input);
519 fun = fun_gmp_sscanf;
523 fun = fun_gmp_fscanf;
527 if (data[i].not_glibc)
530 if (! libc_scanf_convert (fmt))
532 name = "standard sscanf";
537 if (data[i].not_glibc)
540 if (! libc_scanf_convert (fmt))
542 name = "standard fscanf";
556 mpz_set_si (got, -999L);
558 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
560 got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
566 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
568 got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
569 mpz_set_si (got, got_l);
576 MPZ_CHECK_FORMAT (got);
578 if (got_ret != want_ret)
580 printf ("%s wrong return value\n", name);
583 if (want_ret == 1 && mpz_cmp (want, got) != 0)
585 printf ("%s wrong result\n", name);
588 if (got_upto != want_upto)
590 printf ("%s wrong upto\n", name);
593 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
595 printf ("%s wrong ftell\n", name);
600 printf (" fmt \"%s\"\n", data[i].fmt);
601 printf (" input \"%s\"\n", data[i].input);
602 printf (" ignore %d\n", ignore);
603 printf (" ret want=%d\n", want_ret);
604 printf (" got =%d\n", got_ret);
605 mpz_trace (" value want", want);
606 mpz_trace (" got ", got);
607 printf (" upto want =%d\n", want_upto);
608 printf (" got =%d\n", got_upto);
611 printf (" ftell want =%ld\n", want_ftell);
612 printf (" got =%ld\n", got_ftell);
626 static const struct {
635 { "%Qd", "0", "0", 1, -1 },
636 { "%Qd", "1", "1", 1, -1 },
637 { "%Qd", "123", "123", 1, -1 },
638 { "%Qd", "+0", "0", 1, -1 },
639 { "%Qd", "+1", "1", 1, -1 },
640 { "%Qd", "+123", "123", 1, -1 },
641 { "%Qd", "-0", "0", 1, -1 },
642 { "%Qd", "-1", "-1", 1, -1 },
643 { "%Qd", "-123", "-123", 1, -1 },
645 { "%Qo", "0", "0", 1, -1 },
646 { "%Qo", "173", "123", 1, -1 },
647 { "%Qo", "+0", "0", 1, -1 },
648 { "%Qo", "+173", "123", 1, -1 },
649 { "%Qo", "-0", "0", 1, -1 },
650 { "%Qo", "-173", "-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 { "%Qx", "0", "0", 1, -1 },
671 { "%Qx", "7B", "123", 1, -1 },
672 { "%Qx", "7B", "123", 1, -1 },
673 { "%Qx", "+0", "0", 1, -1 },
674 { "%Qx", "+7B", "123", 1, -1 },
675 { "%Qx", "+7B", "123", 1, -1 },
676 { "%Qx", "-0", "-0", 1, -1 },
677 { "%Qx", "-7B", "-123", 1, -1 },
678 { "%Qx", "-7B", "-123", 1, -1 },
679 { "%QX", "0", "0", 1, -1 },
680 { "%QX", "7B", "123", 1, -1 },
681 { "%QX", "7B", "123", 1, -1 },
682 { "%QX", "+0", "0", 1, -1 },
683 { "%QX", "+7B", "123", 1, -1 },
684 { "%QX", "+7B", "123", 1, -1 },
685 { "%QX", "-0", "-0", 1, -1 },
686 { "%QX", "-7B", "-123", 1, -1 },
687 { "%QX", "-7B", "-123", 1, -1 },
689 { "%Qi", "0", "0", 1, -1 },
690 { "%Qi", "1", "1", 1, -1 },
691 { "%Qi", "123", "123", 1, -1 },
692 { "%Qi", "+0", "0", 1, -1 },
693 { "%Qi", "+1", "1", 1, -1 },
694 { "%Qi", "+123", "123", 1, -1 },
695 { "%Qi", "-0", "0", 1, -1 },
696 { "%Qi", "-1", "-1", 1, -1 },
697 { "%Qi", "-123", "-123", 1, -1 },
699 { "%Qi", "00", "0", 1, -1 },
700 { "%Qi", "0173", "123", 1, -1 },
701 { "%Qi", "+00", "0", 1, -1 },
702 { "%Qi", "+0173", "123", 1, -1 },
703 { "%Qi", "-00", "0", 1, -1 },
704 { "%Qi", "-0173", "-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 { "%Qi", "0x0", "0", 1, -1 },
725 { "%Qi", "0x7B", "123", 1, -1 },
726 { "%Qi", "0x7B", "123", 1, -1 },
727 { "%Qi", "+0x0", "0", 1, -1 },
728 { "%Qi", "+0x7B", "123", 1, -1 },
729 { "%Qi", "+0x7B", "123", 1, -1 },
730 { "%Qi", "-0x0", "-0", 1, -1 },
731 { "%Qi", "-0x7B", "-123", 1, -1 },
732 { "%Qi", "-0x7B", "-123", 1, -1 },
733 { "%Qi", "0X0", "0", 1, -1 },
734 { "%Qi", "0X7B", "123", 1, -1 },
735 { "%Qi", "0X7B", "123", 1, -1 },
736 { "%Qi", "+0X0", "0", 1, -1 },
737 { "%Qi", "+0X7B", "123", 1, -1 },
738 { "%Qi", "+0X7B", "123", 1, -1 },
739 { "%Qi", "-0X0", "-0", 1, -1 },
740 { "%Qi", "-0X7B", "-123", 1, -1 },
741 { "%Qi", "-0X7B", "-123", 1, -1 },
743 { "%Qd", " 0", "0", 1, -1 },
744 { "%Qd", " 0", "0", 1, -1 },
745 { "%Qd", " 0", "0", 1, -1 },
746 { "%Qd", "\t0", "0", 1, -1 },
747 { "%Qd", "\t\t0", "0", 1, -1 },
749 { "%Qd", "3/2", "3/2", 1, -1 },
750 { "%Qd", "+3/2", "3/2", 1, -1 },
751 { "%Qd", "-3/2", "-3/2", 1, -1 },
753 { "%Qx", "f/10", "15/16", 1, -1 },
754 { "%Qx", "F/10", "15/16", 1, -1 },
755 { "%QX", "f/10", "15/16", 1, -1 },
756 { "%QX", "F/10", "15/16", 1, -1 },
758 { "%Qo", "20/21", "16/17", 1, -1 },
759 { "%Qo", "-20/21", "-16/17", 1, -1 },
761 { "%Qi", "10/11", "10/11", 1, -1 },
762 { "%Qi", "+10/11", "10/11", 1, -1 },
763 { "%Qi", "-10/11", "-10/11", 1, -1 },
764 { "%Qi", "010/11", "8/11", 1, -1 },
765 { "%Qi", "+010/11", "8/11", 1, -1 },
766 { "%Qi", "-010/11", "-8/11", 1, -1 },
767 { "%Qi", "0x10/11", "16/11", 1, -1 },
768 { "%Qi", "+0x10/11", "16/11", 1, -1 },
769 { "%Qi", "-0x10/11", "-16/11", 1, -1 },
771 { "%Qi", "10/011", "10/9", 1, -1 },
772 { "%Qi", "+10/011", "10/9", 1, -1 },
773 { "%Qi", "-10/011", "-10/9", 1, -1 },
774 { "%Qi", "010/011", "8/9", 1, -1 },
775 { "%Qi", "+010/011", "8/9", 1, -1 },
776 { "%Qi", "-010/011", "-8/9", 1, -1 },
777 { "%Qi", "0x10/011", "16/9", 1, -1 },
778 { "%Qi", "+0x10/011", "16/9", 1, -1 },
779 { "%Qi", "-0x10/011", "-16/9", 1, -1 },
781 { "%Qi", "10/0x11", "10/17", 1, -1 },
782 { "%Qi", "+10/0x11", "10/17", 1, -1 },
783 { "%Qi", "-10/0x11", "-10/17", 1, -1 },
784 { "%Qi", "010/0x11", "8/17", 1, -1 },
785 { "%Qi", "+010/0x11", "8/17", 1, -1 },
786 { "%Qi", "-010/0x11", "-8/17", 1, -1 },
787 { "%Qi", "0x10/0x11", "16/17", 1, -1 },
788 { "%Qi", "+0x10/0x11", "16/17", 1, -1 },
789 { "%Qi", "-0x10/0x11", "-16/17", 1, -1 },
791 { "hello%Qd", "hello0", "0", 1, -1 },
792 { "hello%Qd", "hello 0", "0", 1, -1 },
793 { "hello%Qd", "hello \t0", "0", 1, -1 },
794 { "hello%Qdworld", "hello 0world", "0", 1, -1 },
795 { "hello%Qd", "hello3/2", "3/2", 1, -1 },
797 { "hello%*Qd", "hello0", "-999/121", 0, -1 },
798 { "hello%*Qd", "hello 0", "-999/121", 0, -1 },
799 { "hello%*Qd", "hello \t0", "-999/121", 0, -1 },
800 { "hello%*Qdworld", "hello 0world", "-999/121", 0, -1 },
801 { "hello%*Qdworld", "hello3/2world", "-999/121", 0, -1 },
803 { "%Qd", "", "-999/121", -1, -1 },
804 { "%Qd", " ", "-999/121", -1, -1 },
805 { " %Qd", "", "-999/121", -1, -1 },
806 { "xyz%Qd", "", "-999/121", -1, -1 },
808 { "%*Qd", "", "-999/121", -1, -1 },
809 { " %*Qd", "", "-999/121", -1, -1 },
810 { "xyz%*Qd", "", "-999/121", -1, -1 },
812 /* match something, but invalid */
813 { "%Qd", "-", "-999/121", 0, 1 },
814 { "%Qd", "+", "-999/121", 0, 1 },
815 { "%Qd", "/-", "-999/121", 0, 1 },
816 { "%Qd", "/+", "-999/121", 0, 1 },
817 { "%Qd", "-/", "-999/121", 0, 1 },
818 { "%Qd", "+/", "-999/121", 0, 1 },
819 { "%Qd", "-/-", "-999/121", 0, 1 },
820 { "%Qd", "-/+", "-999/121", 0, 1 },
821 { "%Qd", "+/+", "-999/121", 0, 1 },
822 { "%Qd", "/123", "-999/121", 0, 1 },
823 { "%Qd", "-/123", "-999/121", 0, 1 },
824 { "%Qd", "+/123", "-999/121", 0, 1 },
825 { "%Qd", "123/", "-999/121", 0, 1 },
826 { "%Qd", "123/-", "-999/121", 0, 1 },
827 { "%Qd", "123/+", "-999/121", 0, 1 },
828 { "xyz%Qd", "xyz-", "-999/121", 0, 4 },
829 { "xyz%Qd", "xyz+", "-999/121", 0, 4 },
831 { "%1Qi", "12/57", "1", 1, 1 },
832 { "%2Qi", "12/57", "12", 1, 2 },
833 { "%3Qi", "12/57", "-999/121", 0, -1 },
834 { "%4Qi", "12/57", "12/5", 1, 4 },
835 { "%5Qi", "12/57", "12/57", 1, 5 },
836 { "%6Qi", "12/57", "12/57", 1, 5 },
837 { "%7Qi", "12/57", "12/57", 1, 5 },
839 { "%1Qi", "012/057", "0", 1, 1 },
840 { "%2Qi", "012/057", "01", 1, 2 },
841 { "%3Qi", "012/057", "012", 1, 3 },
842 { "%4Qi", "012/057", "-999/121", 0, -1 },
843 { "%5Qi", "012/057", "012/0", 1, 5 },
844 { "%6Qi", "012/057", "012/5", 1, 6 },
845 { "%7Qi", "012/057", "012/057", 1, 7 },
846 { "%8Qi", "012/057", "012/057", 1, 7 },
847 { "%9Qi", "012/057", "012/057", 1, 7 },
849 { "%1Qi", "0x12/0x57", "0", 1, 1 },
850 { "%2Qi", "0x12/0x57", "-999", 0, 2 },
851 { "%3Qi", "0x12/0x57", "0x1", 1, 3 },
852 { "%4Qi", "0x12/0x57", "0x12", 1, 4 },
853 { "%5Qi", "0x12/0x57", "-999/121", 0, 5 },
854 { "%6Qi", "0x12/0x57", "0x12/0", 1, 6 },
855 { "%7Qi", "0x12/0x57", "-999/121", 0, 7 },
856 { "%8Qi", "0x12/0x57", "0x12/0x5", 1, 8 },
857 { "%9Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
858 { "%10Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
859 { "%11Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
861 { "%Qd", "xyz", "0", 0, 0 },
864 int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
866 long got_l, want_ftell;
875 for (i = 0; i < numberof (data); i++)
877 mpq_set_str_or_abort (want, data[i].want, 0);
879 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
880 strcpy (fmt, data[i].fmt);
883 ignore = (strchr (fmt, '*') != NULL);
885 for (j = 0; j <= 3; j++)
887 want_ret = data[i].ret;
889 want_ftell = data[i].ftell;
890 if (want_ftell == -1)
891 want_ftell = strlen (data[i].input);
892 want_upto = want_ftell;
894 if (want_ret == -1 || (want_ret == 0 && ! ignore))
903 fun = fun_gmp_sscanf;
907 fun = fun_gmp_fscanf;
910 if (strchr (data[i].input, '/') != NULL)
912 if (! libc_scanf_convert (fmt))
914 name = "standard sscanf";
918 if (strchr (data[i].input, '/') != NULL)
920 if (! libc_scanf_convert (fmt))
922 name = "standard fscanf";
936 mpq_set_si (got, -999L, 121L);
938 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
940 got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
946 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
948 got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
949 mpq_set_si (got, got_l, (got_l == -999L ? 121L : 1L));
956 MPZ_CHECK_FORMAT (mpq_numref (got));
957 MPZ_CHECK_FORMAT (mpq_denref (got));
959 if (got_ret != want_ret)
961 printf ("%s wrong return value\n", name);
964 /* use direct mpz compares, since some of the test data is
965 non-canonical and can trip ASSERTs in mpq_equal */
967 && ! (mpz_cmp (mpq_numref(want), mpq_numref(got)) == 0
968 && mpz_cmp (mpq_denref(want), mpq_denref(got)) == 0))
970 printf ("%s wrong result\n", name);
973 if (got_upto != want_upto)
975 printf ("%s wrong upto\n", name);
978 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
980 printf ("%s wrong ftell\n", name);
985 printf (" fmt \"%s\"\n", data[i].fmt);
986 printf (" input \"%s\"\n", data[i].input);
987 printf (" ret want=%d\n", want_ret);
988 printf (" got =%d\n", got_ret);
989 mpq_trace (" value want", want);
990 mpq_trace (" got ", got);
991 printf (" upto want=%d\n", want_upto);
992 printf (" got =%d\n", got_upto);
995 printf (" ftell want =%ld\n", want_ftell);
996 printf (" got =%ld\n", got_ftell);
1010 static const struct {
1015 long ftell; /* or -1 for length of input string */
1019 { "%Ff", "0", "0", 1, -1 },
1020 { "%Fe", "0", "0", 1, -1 },
1021 { "%FE", "0", "0", 1, -1 },
1022 { "%Fg", "0", "0", 1, -1 },
1023 { "%FG", "0", "0", 1, -1 },
1025 { "%Ff", "123", "123", 1, -1 },
1026 { "%Ff", "+123", "123", 1, -1 },
1027 { "%Ff", "-123", "-123", 1, -1 },
1028 { "%Ff", "123.", "123", 1, -1 },
1029 { "%Ff", "+123.", "123", 1, -1 },
1030 { "%Ff", "-123.", "-123", 1, -1 },
1031 { "%Ff", "123.0", "123", 1, -1 },
1032 { "%Ff", "+123.0", "123", 1, -1 },
1033 { "%Ff", "-123.0", "-123", 1, -1 },
1034 { "%Ff", "0123", "123", 1, -1 },
1035 { "%Ff", "-0123", "-123", 1, -1 },
1037 { "%Ff", "123.456e3", "123456", 1, -1 },
1038 { "%Ff", "-123.456e3", "-123456", 1, -1 },
1039 { "%Ff", "123.456e+3", "123456", 1, -1 },
1040 { "%Ff", "-123.456e+3", "-123456", 1, -1 },
1041 { "%Ff", "123000e-3", "123", 1, -1 },
1042 { "%Ff", "-123000e-3", "-123", 1, -1 },
1043 { "%Ff", "123000.e-3", "123", 1, -1 },
1044 { "%Ff", "-123000.e-3", "-123", 1, -1 },
1046 { "%Ff", "123.456E3", "123456", 1, -1 },
1047 { "%Ff", "-123.456E3", "-123456", 1, -1 },
1048 { "%Ff", "123.456E+3", "123456", 1, -1 },
1049 { "%Ff", "-123.456E+3", "-123456", 1, -1 },
1050 { "%Ff", "123000E-3", "123", 1, -1 },
1051 { "%Ff", "-123000E-3", "-123", 1, -1 },
1052 { "%Ff", "123000.E-3", "123", 1, -1 },
1053 { "%Ff", "-123000.E-3", "-123", 1, -1 },
1055 { "%Ff", ".456e3", "456", 1, -1 },
1056 { "%Ff", "-.456e3", "-456", 1, -1 },
1057 { "%Ff", ".456e+3", "456", 1, -1 },
1058 { "%Ff", "-.456e+3", "-456", 1, -1 },
1060 { "%Ff", " 0", "0", 1, -1 },
1061 { "%Ff", " 0", "0", 1, -1 },
1062 { "%Ff", " 0", "0", 1, -1 },
1063 { "%Ff", "\t0", "0", 1, -1 },
1064 { "%Ff", "\t\t0", "0", 1, -1 },
1066 { "hello%Fg", "hello0", "0", 1, -1 },
1067 { "hello%Fg", "hello 0", "0", 1, -1 },
1068 { "hello%Fg", "hello \t0", "0", 1, -1 },
1069 { "hello%Fgworld", "hello 0world", "0", 1, -1 },
1070 { "hello%Fg", "hello3.0", "3.0", 1, -1 },
1072 { "hello%*Fg", "hello0", "-999", 0, -1 },
1073 { "hello%*Fg", "hello 0", "-999", 0, -1 },
1074 { "hello%*Fg", "hello \t0", "-999", 0, -1 },
1075 { "hello%*Fgworld", "hello 0world", "-999", 0, -1 },
1076 { "hello%*Fgworld", "hello3.0world", "-999", 0, -1 },
1078 { "%Ff", "", "-999", -1, -1 },
1079 { "%Ff", " ", "-999", -1, -1 },
1080 { "%Ff", "\t", "-999", -1, -1 },
1081 { "%Ff", " \t", "-999", -1, -1 },
1082 { " %Ff", "", "-999", -1, -1 },
1083 { "xyz%Ff", "", "-999", -1, -1 },
1085 { "%*Ff", "", "-999", -1, -1 },
1086 { " %*Ff", "", "-999", -1, -1 },
1087 { "xyz%*Ff", "", "-999", -1, -1 },
1089 { "%Ff", "xyz", "0", 0 },
1091 /* various non-empty but invalid */
1092 { "%Ff", "-", "-999", 0, 1 },
1093 { "%Ff", "+", "-999", 0, 1 },
1094 { "xyz%Ff", "xyz-", "-999", 0, 4 },
1095 { "xyz%Ff", "xyz+", "-999", 0, 4 },
1096 { "%Ff", "-.", "-999", 0, 2 },
1097 { "%Ff", "+.", "-999", 0, 2 },
1098 { "%Ff", ".e", "-999", 0, 1 },
1099 { "%Ff", "-.e", "-999", 0, 2 },
1100 { "%Ff", "+.e", "-999", 0, 2 },
1101 { "%Ff", ".E", "-999", 0, 1 },
1102 { "%Ff", "-.E", "-999", 0, 2 },
1103 { "%Ff", "+.E", "-999", 0, 2 },
1104 { "%Ff", ".e123", "-999", 0, 1 },
1105 { "%Ff", "-.e123", "-999", 0, 2 },
1106 { "%Ff", "+.e123", "-999", 0, 2 },
1107 { "%Ff", "123e", "-999", 0, 4 },
1108 { "%Ff", "-123e", "-999", 0, 5 },
1109 { "%Ff", "123e-", "-999", 0, 5 },
1110 { "%Ff", "-123e-", "-999", 0, 6 },
1111 { "%Ff", "123e+", "-999", 0, 5 },
1112 { "%Ff", "-123e+", "-999", 0, 6 },
1113 { "%Ff", "123e-Z", "-999", 0, 5 },
1116 { "%Ff", "0x123p0", "291", 1, -1 },
1117 { "%Ff", "0x123P0", "291", 1, -1 },
1118 { "%Ff", "0X123p0", "291", 1, -1 },
1119 { "%Ff", "0X123P0", "291", 1, -1 },
1120 { "%Ff", "-0x123p0", "-291", 1, -1 },
1121 { "%Ff", "+0x123p0", "291", 1, -1 },
1122 { "%Ff", "0x123.p0", "291", 1, -1 },
1123 { "%Ff", "0x12.3p4", "291", 1, -1 },
1124 { "%Ff", "-0x12.3p4", "-291", 1, -1 },
1125 { "%Ff", "+0x12.3p4", "291", 1, -1 },
1126 { "%Ff", "0x1230p-4", "291", 1, -1 },
1127 { "%Ff", "-0x1230p-4", "-291", 1, -1 },
1128 { "%Ff", "+0x1230p-4", "291", 1, -1 },
1129 { "%Ff", "+0x.1230p12", "291", 1, -1 },
1130 { "%Ff", "+0x123000p-12", "291", 1, -1 },
1131 { "%Ff", "0x123 p12", "291", 1, 5 },
1132 { "%Ff", "0x9 9", "9", 1, 3 },
1133 { "%Ff", "0x01", "1", 1, 4 },
1134 { "%Ff", "0x23", "35", 1, 4 },
1135 { "%Ff", "0x45", "69", 1, 4 },
1136 { "%Ff", "0x67", "103", 1, 4 },
1137 { "%Ff", "0x89", "137", 1, 4 },
1138 { "%Ff", "0xAB", "171", 1, 4 },
1139 { "%Ff", "0xCD", "205", 1, 4 },
1140 { "%Ff", "0xEF", "239", 1, 4 },
1141 { "%Ff", "0xab", "171", 1, 4 },
1142 { "%Ff", "0xcd", "205", 1, 4 },
1143 { "%Ff", "0xef", "239", 1, 4 },
1144 { "%Ff", "0x100p0A", "256", 1, 7 },
1145 { "%Ff", "0x1p9", "512", 1, -1 },
1147 /* invalid hex floats */
1148 { "%Ff", "0x", "-999", 0, 2 },
1149 { "%Ff", "-0x", "-999", 0, 3 },
1150 { "%Ff", "+0x", "-999", 0, 3 },
1151 { "%Ff", "0x-", "-999", 0, 2 },
1152 { "%Ff", "0x+", "-999", 0, 2 },
1153 { "%Ff", "0x.", "-999", 0, 3 },
1154 { "%Ff", "-0x.", "-999", 0, 4 },
1155 { "%Ff", "+0x.", "-999", 0, 4 },
1156 { "%Ff", "0x.p", "-999", 0, 3 },
1157 { "%Ff", "-0x.p", "-999", 0, 4 },
1158 { "%Ff", "+0x.p", "-999", 0, 4 },
1159 { "%Ff", "0x.P", "-999", 0, 3 },
1160 { "%Ff", "-0x.P", "-999", 0, 4 },
1161 { "%Ff", "+0x.P", "-999", 0, 4 },
1162 { "%Ff", ".p123", "-999", 0, 1 },
1163 { "%Ff", "-.p123", "-999", 0, 2 },
1164 { "%Ff", "+.p123", "-999", 0, 2 },
1165 { "%Ff", "0x1p", "-999", 0, 4 },
1166 { "%Ff", "0x1p-", "-999", 0, 5 },
1167 { "%Ff", "0x1p+", "-999", 0, 5 },
1168 { "%Ff", "0x123p 12", "291", 0, 6 },
1169 { "%Ff", "0x 123p12", "291", 0, 2 },
1173 int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
1185 for (i = 0; i < numberof (data); i++)
1187 mpf_set_str_or_abort (want, data[i].want, 10);
1189 ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
1190 strcpy (fmt, data[i].fmt);
1193 ignore = (strchr (fmt, '*') != NULL);
1195 for (j = 0; j <= 3; j++)
1197 want_ret = data[i].ret;
1199 want_ftell = data[i].ftell;
1200 if (want_ftell == -1)
1201 want_ftell = strlen (data[i].input);
1202 want_upto = want_ftell;
1204 if (want_ret == -1 || (want_ret == 0 && ! ignore))
1209 name = "gmp_sscanf";
1210 fun = fun_gmp_sscanf;
1213 name = "gmp_fscanf";
1214 fun = fun_gmp_fscanf;
1217 if (! libc_scanf_convert (fmt))
1219 name = "standard sscanf";
1223 if (! libc_scanf_convert (fmt))
1225 name = "standard fscanf";
1239 mpf_set_si (got, -999L);
1241 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
1243 got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
1249 got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
1251 got_ret = (*fun) (data[i].input, fmt, &got_d, &got_upto);
1252 mpf_set_d (got, got_d);
1259 MPF_CHECK_FORMAT (got);
1261 if (got_ret != want_ret)
1263 printf ("%s wrong return value\n", name);
1266 if (want_ret == 1 && mpf_cmp (want, got) != 0)
1268 printf ("%s wrong result\n", name);
1271 if (got_upto != want_upto)
1273 printf ("%s wrong upto\n", name);
1276 if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
1278 printf ("%s wrong ftell\n", name);
1283 printf (" fmt \"%s\"\n", data[i].fmt);
1284 printf (" input \"%s\"\n", data[i].input);
1285 printf (" ret want=%d\n", want_ret);
1286 printf (" got =%d\n", got_ret);
1287 mpf_trace (" value want", want);
1288 mpf_trace (" got ", got);
1289 printf (" upto want=%d\n", want_upto);
1290 printf (" got =%d\n", got_upto);
1291 if (got_ftell != -1)
1293 printf (" ftell want =%ld\n", want_ftell);
1294 printf (" got =%ld\n", got_ftell);
1314 gmp_sscanf (" ", " %*n", &n);
1315 ASSERT_ALWAYS (n == 123);
1319 fromstring_gmp_fscanf (" ", " %*n", &n);
1320 ASSERT_ALWAYS (n == 123);
1324 #define CHECK_N(type, string) \
1330 x[0] = ~ (type) 0; \
1331 x[1] = ~ (type) 0; \
1332 sprintf (fmt, "abc%%%sn", string); \
1333 ret = gmp_sscanf ("abc", fmt, &x[0]); \
1335 ASSERT_ALWAYS (ret == 0); \
1337 /* should write whole of x[0] and none of x[1] */ \
1338 ASSERT_ALWAYS (x[0] == 3); \
1339 ASSERT_ALWAYS (x[1] == (type) ~ (type) 0); \
1343 CHECK_N (char, "hh");
1344 CHECK_N (long, "l");
1346 CHECK_N (long long, "L");
1349 CHECK_N (intmax_t, "j");
1352 CHECK_N (ptrdiff_t, "t");
1354 CHECK_N (short, "h");
1355 CHECK_N (size_t, "z");
1360 mpz_init_set_si (x[0], -987L);
1361 mpz_init_set_si (x[1], 654L);
1362 ret = gmp_sscanf ("xyz ", "xyz%Zn", x[0]);
1363 MPZ_CHECK_FORMAT (x[0]);
1364 MPZ_CHECK_FORMAT (x[1]);
1365 ASSERT_ALWAYS (ret == 0);
1366 ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
1367 ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
1374 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Zn", x);
1375 ASSERT_ALWAYS (ret == 0);
1376 ASSERT_ALWAYS (mpz_cmp_ui (x, 3L) == 0);
1385 mpq_set_ui (x[0], 987L, 654L);
1386 mpq_set_ui (x[1], 4115L, 226L);
1387 ret = gmp_sscanf ("xyz ", "xyz%Qn", x[0]);
1388 MPQ_CHECK_FORMAT (x[0]);
1389 MPQ_CHECK_FORMAT (x[1]);
1390 ASSERT_ALWAYS (ret == 0);
1391 ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
1392 ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
1399 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Qn", x);
1400 ASSERT_ALWAYS (ret == 0);
1401 ASSERT_ALWAYS (mpq_cmp_ui (x, 3L, 1L) == 0);
1410 mpf_set_ui (x[0], 987L);
1411 mpf_set_ui (x[1], 654L);
1412 ret = gmp_sscanf ("xyz ", "xyz%Fn", x[0]);
1413 MPF_CHECK_FORMAT (x[0]);
1414 MPF_CHECK_FORMAT (x[1]);
1415 ASSERT_ALWAYS (ret == 0);
1416 ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
1417 ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
1424 ret = fromstring_gmp_fscanf ("xyz ", "xyz%Fn", x);
1425 ASSERT_ALWAYS (ret == 0);
1426 ASSERT_ALWAYS (mpf_cmp_ui (x, 3L) == 0);
1437 int a=9, b=8, c=7, n=66;
1440 ret = gmp_sscanf ("1 2 3 4", "%d %d %d %Zd%n",
1442 ASSERT_ALWAYS (ret == 4);
1443 ASSERT_ALWAYS (a == 1);
1444 ASSERT_ALWAYS (b == 2);
1445 ASSERT_ALWAYS (c == 3);
1446 ASSERT_ALWAYS (n == 7);
1447 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1451 int a=9, b=8, c=7, n=66;
1454 ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %d %d %Zd%n",
1456 ASSERT_ALWAYS (ret == 4);
1457 ASSERT_ALWAYS (a == 1);
1458 ASSERT_ALWAYS (b == 2);
1459 ASSERT_ALWAYS (c == 3);
1460 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1461 ASSERT_ALWAYS (n == 7);
1462 ASSERT_ALWAYS (got_ftell == 7);
1470 ret = gmp_sscanf ("1 2 3 4", "%d %*d %*d %Zd%n", &a, z, &n);
1471 ASSERT_ALWAYS (ret == 2);
1472 ASSERT_ALWAYS (a == 1);
1473 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1474 ASSERT_ALWAYS (n == 7);
1481 ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %*d %*d %Zd%n",
1483 ASSERT_ALWAYS (ret == 2);
1484 ASSERT_ALWAYS (a == 1);
1485 ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1486 ASSERT_ALWAYS (n == 7);
1487 ASSERT_ALWAYS (got_ftell == 7);
1491 /* EOF for no matching */
1494 ret = gmp_sscanf (" ", "%s", buf);
1495 ASSERT_ALWAYS (ret == EOF);
1496 ret = fromstring_gmp_fscanf (" ", "%s", buf);
1497 ASSERT_ALWAYS (ret == EOF);
1498 if (option_libc_scanf)
1500 ret = sscanf (" ", "%s", buf);
1501 ASSERT_ALWAYS (ret == EOF);
1502 ret = fun_fscanf (" ", "%s", buf, NULL);
1503 ASSERT_ALWAYS (ret == EOF);
1507 /* suppressed field, then eof */
1510 if (test_sscanf_eof_ok ())
1512 ret = gmp_sscanf ("123", "%*d%d", &x);
1513 ASSERT_ALWAYS (ret == EOF);
1515 ret = fromstring_gmp_fscanf ("123", "%*d%d", &x);
1516 ASSERT_ALWAYS (ret == EOF);
1517 if (option_libc_scanf)
1519 ret = sscanf ("123", "%*d%d", &x);
1520 ASSERT_ALWAYS (ret == EOF);
1521 ret = fun_fscanf ("123", "%*d%d", &x, NULL);
1522 ASSERT_ALWAYS (ret == EOF);
1528 ret = gmp_sscanf ("123", "%*Zd%Zd", x);
1529 ASSERT_ALWAYS (ret == EOF);
1530 ret = fromstring_gmp_fscanf ("123", "%*Zd%Zd", x);
1531 ASSERT_ALWAYS (ret == EOF);
1535 /* %[...], glibc only */
1541 ret = gmp_sscanf ("abcdefgh", "%[a-d]ef%n", buf, &n);
1542 ASSERT_ALWAYS (ret == 1);
1543 cmp = strcmp (buf, "abcd");
1544 ASSERT_ALWAYS (cmp == 0);
1545 ASSERT_ALWAYS (n == 6);
1551 ret = gmp_sscanf ("xyza", "%[^a]a%n", buf, &n);
1552 ASSERT_ALWAYS (ret == 1);
1553 cmp = strcmp (buf, "xyz");
1554 ASSERT_ALWAYS (cmp == 0);
1555 ASSERT_ALWAYS (n == 4);
1561 ret = gmp_sscanf ("ab]ab]", "%[]ab]%n", buf, &n);
1562 ASSERT_ALWAYS (ret == 1);
1563 cmp = strcmp (buf, "ab]ab]");
1564 ASSERT_ALWAYS (cmp == 0);
1565 ASSERT_ALWAYS (n == 6);
1571 ret = gmp_sscanf ("xyzb", "%[^]ab]b%n", buf, &n);
1572 ASSERT_ALWAYS (ret == 1);
1573 cmp = strcmp (buf, "xyz");
1574 ASSERT_ALWAYS (cmp == 0);
1575 ASSERT_ALWAYS (n == 4);
1579 /* %zd etc won't be accepted by sscanf on old systems, and running
1580 something to see if they work might be bad, so only try it on glibc,
1581 and only on a new enough version (glibc 2.0 doesn't have %zd) */
1582 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
1587 ret = gmp_sscanf ("456 789", "%zd %Zd", &s, z);
1588 ASSERT_ALWAYS (ret == 2);
1589 ASSERT_ALWAYS (s == 456);
1590 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1597 ret = gmp_sscanf ("456 789", "%td %Zd", &d, z);
1598 ASSERT_ALWAYS (ret == 2);
1599 ASSERT_ALWAYS (d == 456);
1600 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1607 ret = gmp_sscanf ("456 789", "%Ld %Zd", &ll, z);
1608 ASSERT_ALWAYS (ret == 2);
1609 ASSERT_ALWAYS (ll == 456);
1610 ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1617 main (int argc, char *argv[])
1619 if (argc > 1 && strcmp (argv[1], "-s") == 0)
1620 option_libc_scanf = 1;