t-scanf.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:49k
- /* Test gmp_scanf and related functions.
- Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- This file is part of the GNU MP Library.
- The GNU MP Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
- The GNU MP Library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
- /* Usage: t-scanf [-s]
- -s Check the data against the system scanf, where possible. This is
- only an option since we don't want to fail if the system scanf is
- faulty or strange.
- There's some fairly unattractive repetition between check_z, check_q and
- check_f, but enough differences to make a common loop or a set of macros
- seem like too much trouble. */
- #include "config.h"
- #if HAVE_STDARG
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #endif
- #include <stddef.h> /* for ptrdiff_t */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #if HAVE_INTTYPES_H
- # include <inttypes.h> /* for intmax_t */
- #else
- # if HAVE_STDINT_H
- # include <stdint.h>
- # endif
- #endif
- #if HAVE_UNISTD_H
- #include <unistd.h> /* for unlink */
- #endif
- #include "gmp.h"
- #include "gmp-impl.h"
- #include "tests.h"
- #define TEMPFILE "t-scanf.tmp"
- int option_libc_scanf = 0;
- typedef int (*fun_t) __GMP_PROTO ((const char *, const char *, void *, void *));
- /* This problem was seen on powerpc7450-apple-darwin7.0.0, sscanf returns 0
- where it should return EOF. A workaround in gmp_sscanf would be a bit
- tedious, and since this is a rather obvious libc bug, quite likely
- affecting other programs, we'll just suppress affected tests for now. */
- int
- test_sscanf_eof_ok (void)
- {
- static int result = -1;
- if (result == -1)
- {
- int x;
- if (sscanf ("", "%d", &x) == EOF)
- {
- result = 1;
- }
- else
- {
- printf ("Warning, sscanf("","%%d",&x) doesn't return EOF.n");
- printf ("This affects gmp_sscanf, tests involving it will be suppressed.n");
- printf ("You should try to get a fix for your libc.n");
- result = 0;
- }
- }
- return result;
- }
- /* Convert fmt from a GMP scanf format string to an equivalent for a plain
- libc scanf, for example "%Zd" becomes "%ld". Return 1 if this succeeds,
- 0 if it cannot (or should not) be done. */
- int
- libc_scanf_convert (char *fmt)
- {
- char *p = fmt;
- if (! option_libc_scanf)
- return 0;
- for ( ; *fmt != ' '; fmt++)
- {
- switch (*fmt) {
- case 'F':
- case 'Q':
- case 'Z':
- /* transmute */
- *p++ = 'l';
- break;
- default:
- *p++ = *fmt;
- break;
- }
- }
- *p = ' ';
- return 1;
- }
- long got_ftell;
- int fromstring_next_c;
- /* Call gmp_fscanf, reading the "input" string data provided. */
- int
- #if HAVE_STDARG
- fromstring_gmp_fscanf (const char *input, const char *fmt, ...)
- #else
- fromstring_gmp_fscanf (va_alist)
- va_dcl
- #endif
- {
- va_list ap;
- FILE *fp;
- int ret;
- #if HAVE_STDARG
- va_start (ap, fmt);
- #else
- const char *input;
- const char *fmt;
- va_start (ap);
- input = va_arg (ap, const char *);
- fmt = va_arg (ap, const char *);
- #endif
- fp = fopen (TEMPFILE, "w+");
- ASSERT_ALWAYS (fp != NULL);
- ASSERT_ALWAYS (fputs (input, fp) != EOF);
- ASSERT_ALWAYS (fflush (fp) == 0);
- rewind (fp);
- ret = gmp_vfscanf (fp, fmt, ap);
- got_ftell = ftell (fp);
- ASSERT_ALWAYS (got_ftell != -1L);
- fromstring_next_c = getc (fp);
- ASSERT_ALWAYS (fclose (fp) == 0);
- va_end (ap);
- return ret;
- }
- int
- fun_gmp_sscanf (const char *input, const char *fmt, void *a1, void *a2)
- {
- if (a2 == NULL)
- return gmp_sscanf (input, fmt, a1);
- else
- return gmp_sscanf (input, fmt, a1, a2);
- }
- int
- fun_gmp_fscanf (const char *input, const char *fmt, void *a1, void *a2)
- {
- if (a2 == NULL)
- return fromstring_gmp_fscanf (input, fmt, a1);
- else
- return fromstring_gmp_fscanf (input, fmt, a1, a2);
- }
- int
- fun_fscanf (const char *input, const char *fmt, void *a1, void *a2)
- {
- FILE *fp;
- int ret;
- fp = fopen (TEMPFILE, "w+");
- ASSERT_ALWAYS (fp != NULL);
- ASSERT_ALWAYS (fputs (input, fp) != EOF);
- ASSERT_ALWAYS (fflush (fp) == 0);
- rewind (fp);
- if (a2 == NULL)
- ret = fscanf (fp, fmt, a1);
- else
- ret = fscanf (fp, fmt, a1, a2);
- got_ftell = ftell (fp);
- ASSERT_ALWAYS (got_ftell != -1L);
- fromstring_next_c = getc (fp);
- ASSERT_ALWAYS (fclose (fp) == 0);
- return ret;
- }
- /* On various old systems, for instance HP-UX 9, the C library sscanf needs
- to be able to write into the input string. Ensure that this is possible,
- when gcc is putting the test data into a read-only section.
- Actually we ought to only need this under SSCANF_WRITABLE_INPUT from
- configure, but it's just as easy to do it unconditionally, and in any
- case this code is only executed under the -s option. */
- int
- fun_sscanf (const char *input, const char *fmt, void *a1, void *a2)
- {
- char *input_writable;
- size_t size;
- int ret;
- size = strlen (input) + 1;
- input_writable = (*__gmp_allocate_func) (size);
- memcpy (input_writable, input, size);
- if (a2 == NULL)
- ret = sscanf (input_writable, fmt, a1);
- else
- ret = sscanf (input_writable, fmt, a1, a2);
- (*__gmp_free_func) (input_writable, size);
- return ret;
- }
- /* whether the format string consists entirely of ignored fields */
- int
- fmt_allignore (const char *fmt)
- {
- int saw_star = 1;
- for ( ; *fmt != ' '; fmt++)
- {
- switch (*fmt) {
- case '%':
- if (! saw_star)
- return 0;
- saw_star = 0;
- break;
- case '*':
- saw_star = 1;
- break;
- }
- }
- return 1;
- }
- void
- check_z (void)
- {
- static const struct {
- const char *fmt;
- const char *input;
- const char *want;
- int want_ret;
- long want_ftell;
- int want_upto;
- int not_glibc;
- } data[] = {
- { "%Zd", "0", "0", 1, -1, -1 },
- { "%Zd", "1", "1", 1, -1, -1 },
- { "%Zd", "123", "123", 1, -1, -1 },
- { "%Zd", "+0", "0", 1, -1, -1 },
- { "%Zd", "+1", "1", 1, -1, -1 },
- { "%Zd", "+123", "123", 1, -1, -1 },
- { "%Zd", "-0", "0", 1, -1, -1 },
- { "%Zd", "-1", "-1", 1, -1, -1 },
- { "%Zd", "-123", "-123", 1, -1, -1 },
- { "%Zo", "0", "0", 1, -1, -1 },
- { "%Zo", "173", "123", 1, -1, -1 },
- { "%Zo", "+0", "0", 1, -1, -1 },
- { "%Zo", "+173", "123", 1, -1, -1 },
- { "%Zo", "-0", "0", 1, -1, -1 },
- { "%Zo", "-173", "-123", 1, -1, -1 },
- { "%Zx", "0", "0", 1, -1, -1 },
- { "%Zx", "7b", "123", 1, -1, -1 },
- { "%Zx", "7b", "123", 1, -1, -1 },
- { "%Zx", "+0", "0", 1, -1, -1 },
- { "%Zx", "+7b", "123", 1, -1, -1 },
- { "%Zx", "+7b", "123", 1, -1, -1 },
- { "%Zx", "-0", "-0", 1, -1, -1 },
- { "%Zx", "-7b", "-123", 1, -1, -1 },
- { "%Zx", "-7b", "-123", 1, -1, -1 },
- { "%ZX", "0", "0", 1, -1, -1 },
- { "%ZX", "7b", "123", 1, -1, -1 },
- { "%ZX", "7b", "123", 1, -1, -1 },
- { "%ZX", "+0", "0", 1, -1, -1 },
- { "%ZX", "+7b", "123", 1, -1, -1 },
- { "%ZX", "+7b", "123", 1, -1, -1 },
- { "%ZX", "-0", "-0", 1, -1, -1 },
- { "%ZX", "-7b", "-123", 1, -1, -1 },
- { "%ZX", "-7b", "-123", 1, -1, -1 },
- { "%Zx", "0", "0", 1, -1, -1 },
- { "%Zx", "7B", "123", 1, -1, -1 },
- { "%Zx", "7B", "123", 1, -1, -1 },
- { "%Zx", "+0", "0", 1, -1, -1 },
- { "%Zx", "+7B", "123", 1, -1, -1 },
- { "%Zx", "+7B", "123", 1, -1, -1 },
- { "%Zx", "-0", "-0", 1, -1, -1 },
- { "%Zx", "-7B", "-123", 1, -1, -1 },
- { "%Zx", "-7B", "-123", 1, -1, -1 },
- { "%ZX", "0", "0", 1, -1, -1 },
- { "%ZX", "7B", "123", 1, -1, -1 },
- { "%ZX", "7B", "123", 1, -1, -1 },
- { "%ZX", "+0", "0", 1, -1, -1 },
- { "%ZX", "+7B", "123", 1, -1, -1 },
- { "%ZX", "+7B", "123", 1, -1, -1 },
- { "%ZX", "-0", "-0", 1, -1, -1 },
- { "%ZX", "-7B", "-123", 1, -1, -1 },
- { "%ZX", "-7B", "-123", 1, -1, -1 },
- { "%Zi", "0", "0", 1, -1, -1 },
- { "%Zi", "1", "1", 1, -1, -1 },
- { "%Zi", "123", "123", 1, -1, -1 },
- { "%Zi", "+0", "0", 1, -1, -1 },
- { "%Zi", "+1", "1", 1, -1, -1 },
- { "%Zi", "+123", "123", 1, -1, -1 },
- { "%Zi", "-0", "0", 1, -1, -1 },
- { "%Zi", "-1", "-1", 1, -1, -1 },
- { "%Zi", "-123", "-123", 1, -1, -1 },
- { "%Zi", "00", "0", 1, -1, -1 },
- { "%Zi", "0173", "123", 1, -1, -1 },
- { "%Zi", "+00", "0", 1, -1, -1 },
- { "%Zi", "+0173", "123", 1, -1, -1 },
- { "%Zi", "-00", "0", 1, -1, -1 },
- { "%Zi", "-0173", "-123", 1, -1, -1 },
- { "%Zi", "0x0", "0", 1, -1, -1 },
- { "%Zi", "0x7b", "123", 1, -1, -1 },
- { "%Zi", "0x7b", "123", 1, -1, -1 },
- { "%Zi", "+0x0", "0", 1, -1, -1 },
- { "%Zi", "+0x7b", "123", 1, -1, -1 },
- { "%Zi", "+0x7b", "123", 1, -1, -1 },
- { "%Zi", "-0x0", "-0", 1, -1, -1 },
- { "%Zi", "-0x7b", "-123", 1, -1, -1 },
- { "%Zi", "-0x7b", "-123", 1, -1, -1 },
- { "%Zi", "0X0", "0", 1, -1, -1 },
- { "%Zi", "0X7b", "123", 1, -1, -1 },
- { "%Zi", "0X7b", "123", 1, -1, -1 },
- { "%Zi", "+0X0", "0", 1, -1, -1 },
- { "%Zi", "+0X7b", "123", 1, -1, -1 },
- { "%Zi", "+0X7b", "123", 1, -1, -1 },
- { "%Zi", "-0X0", "-0", 1, -1, -1 },
- { "%Zi", "-0X7b", "-123", 1, -1, -1 },
- { "%Zi", "-0X7b", "-123", 1, -1, -1 },
- { "%Zi", "0x0", "0", 1, -1, -1 },
- { "%Zi", "0x7B", "123", 1, -1, -1 },
- { "%Zi", "0x7B", "123", 1, -1, -1 },
- { "%Zi", "+0x0", "0", 1, -1, -1 },
- { "%Zi", "+0x7B", "123", 1, -1, -1 },
- { "%Zi", "+0x7B", "123", 1, -1, -1 },
- { "%Zi", "-0x0", "-0", 1, -1, -1 },
- { "%Zi", "-0x7B", "-123", 1, -1, -1 },
- { "%Zi", "-0x7B", "-123", 1, -1, -1 },
- { "%Zi", "0X0", "0", 1, -1, -1 },
- { "%Zi", "0X7B", "123", 1, -1, -1 },
- { "%Zi", "0X7B", "123", 1, -1, -1 },
- { "%Zi", "+0X0", "0", 1, -1, -1 },
- { "%Zi", "+0X7B", "123", 1, -1, -1 },
- { "%Zi", "+0X7B", "123", 1, -1, -1 },
- { "%Zi", "-0X0", "-0", 1, -1, -1 },
- { "%Zi", "-0X7B", "-123", 1, -1, -1 },
- { "%Zi", "-0X7B", "-123", 1, -1, -1 },
- { "%Zd", " 0", "0", 1, -1, -1 },
- { "%Zd", " 0", "0", 1, -1, -1 },
- { "%Zd", " 0", "0", 1, -1, -1 },
- { "%Zd", "t0", "0", 1, -1, -1 },
- { "%Zd", "tt0", "0", 1, -1, -1 },
- { "hello%Zd", "hello0", "0", 1, -1, -1 },
- { "hello%Zd", "hello 0", "0", 1, -1, -1 },
- { "hello%Zd", "hello t0", "0", 1, -1, -1 },
- { "hello%Zdworld", "hello 0world", "0", 1, -1, -1 },
- { "hello%*Zd", "hello0", "-999", 0, -1, -1 },
- { "hello%*Zd", "hello 0", "-999", 0, -1, -1 },
- { "hello%*Zd", "hello t0", "-999", 0, -1, -1 },
- { "hello%*Zdworld", "hello 0world", "-999", 0, -1, -1 },
- { "%Zd", "", "-999", -1, -1, -555 },
- { "%Zd", " ", "-999", -1, -1, -555 },
- { " %Zd", "", "-999", -1, -1, -555 },
- { "xyz%Zd", "", "-999", -1, -1, -555 },
- { "%*Zd", "", "-999", -1, -1, -555 },
- { " %*Zd", "", "-999", -1, -1, -555 },
- { "xyz%*Zd", "", "-999", -1, -1, -555 },
- { "%Zd", "xyz", "0", 0, 0, -555 },
- /* match something, but invalid */
- { "%Zd", "-", "-999", 0, 1, -555 },
- { "%Zd", "+", "-999", 0, 1, -555 },
- { "xyz%Zd", "xyz-", "-999", 0, 4, -555 },
- { "xyz%Zd", "xyz+", "-999", 0, 4, -555 },
- { "%Zi", "0x", "-999", 0, 2, -555 },
- { "%Zi", "0X", "-999", 0, 2, -555 },
- { "%Zi", "0x-", "-999", 0, 2, -555 },
- { "%Zi", "0X+", "-999", 0, 2, -555 },
- { "%Zi", "-0x", "-999", 0, 3, -555 },
- { "%Zi", "-0X", "-999", 0, 3, -555 },
- { "%Zi", "+0x", "-999", 0, 3, -555 },
- { "%Zi", "+0X", "-999", 0, 3, -555 },
- { "%1Zi", "1234", "1", 1, 1, 1 },
- { "%2Zi", "1234", "12", 1, 2, 2 },
- { "%3Zi", "1234", "123", 1, 3, 3 },
- { "%4Zi", "1234", "1234", 1, 4, 4 },
- { "%5Zi", "1234", "1234", 1, 4, 4 },
- { "%6Zi", "1234", "1234", 1, 4, 4 },
- { "%1Zi", "01234", "0", 1, 1, 1 },
- { "%2Zi", "01234", "01", 1, 2, 2 },
- { "%3Zi", "01234", "012", 1, 3, 3 },
- { "%4Zi", "01234", "0123", 1, 4, 4 },
- { "%5Zi", "01234", "01234", 1, 5, 5 },
- { "%6Zi", "01234", "01234", 1, 5, 5 },
- { "%7Zi", "01234", "01234", 1, 5, 5 },
- { "%1Zi", "0x1234", "0", 1, 1, 1 },
- { "%2Zi", "0x1234", "-999", 0, 2, -555 },
- { "%3Zi", "0x1234", "0x1", 1, 3, 3 },
- { "%4Zi", "0x1234", "0x12", 1, 4, 4 },
- { "%5Zi", "0x1234", "0x123", 1, 5, 5 },
- { "%6Zi", "0x1234", "0x1234", 1, 6, 6 },
- { "%7Zi", "0x1234", "0x1234", 1, 6, 6 },
- { "%8Zi", "0x1234", "0x1234", 1, 6, 6 },
- { "%%xyz%Zd", "%xyz123", "123", 1, -1, -1 },
- { "12%%34%Zd", "12%34567", "567", 1, -1, -1 },
- { "%%%%%Zd", "%%123", "123", 1, -1, -1 },
- /* various subtle EOF cases */
- { "x", "", "-999", EOF, 0, -555 },
- { " x", "", "-999", EOF, 0, -555 },
- { "xyz", "", "-999", EOF, 0, -555 },
- { " ", "", "-999", 0, 0, 0 },
- { " ", " ", "-999", 0, 1, 1 },
- { "%*Zd%Zd", "", "-999", EOF, 0, -555 },
- { "%*Zd%Zd", "123", "-999", EOF, 3, -555 },
- { "x", "x", "-999", 0, 1, 1 },
- { "xyz", "x", "-999", EOF, 1, -555 },
- { "xyz", "xy", "-999", EOF, 2, -555 },
- { "xyz", "xyz", "-999", 0, 3, 3 },
- { "%Zn", "", "0", 0, 0, 0 },
- { " %Zn", "", "0", 0, 0, 0 },
- { " x%Zn", "", "-999", EOF, 0, -555 },
- { "xyz%Zn", "", "-999", EOF, 0, -555 },
- { " x%Zn", "", "-999", EOF, 0, -555 },
- { " %Zn x", " ", "-999", EOF, 1, -555 },
- /* these seem to tickle a bug in glibc 2.2.4 */
- { " x", " ", "-999", EOF, 1, -555, 1 },
- { " xyz", " ", "-999", EOF, 1, -555, 1 },
- { " x%Zn", " ", "-999", EOF, 1, -555, 1 },
- };
- int i, j, ignore;
- int got_ret, want_ret, got_upto, want_upto;
- mpz_t got, want;
- long got_l, want_ftell;
- int error = 0;
- fun_t fun;
- const char *name;
- char fmt[128];
- mpz_init (got);
- mpz_init (want);
- for (i = 0; i < numberof (data); i++)
- {
- mpz_set_str_or_abort (want, data[i].want, 0);
- ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
- strcpy (fmt, data[i].fmt);
- strcat (fmt, "%n");
- ignore = fmt_allignore (fmt);
- for (j = 0; j <= 3; j++)
- {
- want_ret = data[i].want_ret;
- want_ftell = data[i].want_ftell;
- if (want_ftell == -1)
- want_ftell = strlen (data[i].input);
- want_upto = data[i].want_upto;
- if (want_upto == -1)
- want_upto = strlen (data[i].input);
- switch (j) {
- case 0:
- name = "gmp_sscanf";
- fun = fun_gmp_sscanf;
- break;
- case 1:
- name = "gmp_fscanf";
- fun = fun_gmp_fscanf;
- break;
- case 2:
- #ifdef __GLIBC__
- if (data[i].not_glibc)
- continue;
- #endif
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard sscanf";
- fun = fun_sscanf;
- break;
- case 3:
- #ifdef __GLIBC__
- if (data[i].not_glibc)
- continue;
- #endif
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard fscanf";
- fun = fun_fscanf;
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- got_upto = -555;
- got_ftell = -1L;
- switch (j) {
- case 0:
- case 1:
- mpz_set_si (got, -999L);
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
- break;
- case 2:
- case 3:
- got_l = -999L;
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
- mpz_set_si (got, got_l);
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- MPZ_CHECK_FORMAT (got);
- if (got_ret != want_ret)
- {
- printf ("%s wrong return valuen", name);
- error = 1;
- }
- if (want_ret == 1 && mpz_cmp (want, got) != 0)
- {
- printf ("%s wrong resultn", name);
- error = 1;
- }
- if (got_upto != want_upto)
- {
- printf ("%s wrong upton", name);
- error = 1;
- }
- if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
- {
- printf ("%s wrong ftelln", name);
- error = 1;
- }
- if (error)
- {
- printf (" fmt "%s"n", data[i].fmt);
- printf (" input "%s"n", data[i].input);
- printf (" ignore %dn", ignore);
- printf (" ret want=%dn", want_ret);
- printf (" got =%dn", got_ret);
- mpz_trace (" value want", want);
- mpz_trace (" got ", got);
- printf (" upto want =%dn", want_upto);
- printf (" got =%dn", got_upto);
- if (got_ftell != -1)
- {
- printf (" ftell want =%ldn", want_ftell);
- printf (" got =%ldn", got_ftell);
- }
- abort ();
- }
- }
- }
- mpz_clear (got);
- mpz_clear (want);
- }
- void
- check_q (void)
- {
- static const struct {
- const char *fmt;
- const char *input;
- const char *want;
- int ret;
- long ftell;
- } data[] = {
- { "%Qd", "0", "0", 1, -1 },
- { "%Qd", "1", "1", 1, -1 },
- { "%Qd", "123", "123", 1, -1 },
- { "%Qd", "+0", "0", 1, -1 },
- { "%Qd", "+1", "1", 1, -1 },
- { "%Qd", "+123", "123", 1, -1 },
- { "%Qd", "-0", "0", 1, -1 },
- { "%Qd", "-1", "-1", 1, -1 },
- { "%Qd", "-123", "-123", 1, -1 },
- { "%Qo", "0", "0", 1, -1 },
- { "%Qo", "173", "123", 1, -1 },
- { "%Qo", "+0", "0", 1, -1 },
- { "%Qo", "+173", "123", 1, -1 },
- { "%Qo", "-0", "0", 1, -1 },
- { "%Qo", "-173", "-123", 1, -1 },
- { "%Qx", "0", "0", 1, -1 },
- { "%Qx", "7b", "123", 1, -1 },
- { "%Qx", "7b", "123", 1, -1 },
- { "%Qx", "+0", "0", 1, -1 },
- { "%Qx", "+7b", "123", 1, -1 },
- { "%Qx", "+7b", "123", 1, -1 },
- { "%Qx", "-0", "-0", 1, -1 },
- { "%Qx", "-7b", "-123", 1, -1 },
- { "%Qx", "-7b", "-123", 1, -1 },
- { "%QX", "0", "0", 1, -1 },
- { "%QX", "7b", "123", 1, -1 },
- { "%QX", "7b", "123", 1, -1 },
- { "%QX", "+0", "0", 1, -1 },
- { "%QX", "+7b", "123", 1, -1 },
- { "%QX", "+7b", "123", 1, -1 },
- { "%QX", "-0", "-0", 1, -1 },
- { "%QX", "-7b", "-123", 1, -1 },
- { "%QX", "-7b", "-123", 1, -1 },
- { "%Qx", "0", "0", 1, -1 },
- { "%Qx", "7B", "123", 1, -1 },
- { "%Qx", "7B", "123", 1, -1 },
- { "%Qx", "+0", "0", 1, -1 },
- { "%Qx", "+7B", "123", 1, -1 },
- { "%Qx", "+7B", "123", 1, -1 },
- { "%Qx", "-0", "-0", 1, -1 },
- { "%Qx", "-7B", "-123", 1, -1 },
- { "%Qx", "-7B", "-123", 1, -1 },
- { "%QX", "0", "0", 1, -1 },
- { "%QX", "7B", "123", 1, -1 },
- { "%QX", "7B", "123", 1, -1 },
- { "%QX", "+0", "0", 1, -1 },
- { "%QX", "+7B", "123", 1, -1 },
- { "%QX", "+7B", "123", 1, -1 },
- { "%QX", "-0", "-0", 1, -1 },
- { "%QX", "-7B", "-123", 1, -1 },
- { "%QX", "-7B", "-123", 1, -1 },
- { "%Qi", "0", "0", 1, -1 },
- { "%Qi", "1", "1", 1, -1 },
- { "%Qi", "123", "123", 1, -1 },
- { "%Qi", "+0", "0", 1, -1 },
- { "%Qi", "+1", "1", 1, -1 },
- { "%Qi", "+123", "123", 1, -1 },
- { "%Qi", "-0", "0", 1, -1 },
- { "%Qi", "-1", "-1", 1, -1 },
- { "%Qi", "-123", "-123", 1, -1 },
- { "%Qi", "00", "0", 1, -1 },
- { "%Qi", "0173", "123", 1, -1 },
- { "%Qi", "+00", "0", 1, -1 },
- { "%Qi", "+0173", "123", 1, -1 },
- { "%Qi", "-00", "0", 1, -1 },
- { "%Qi", "-0173", "-123", 1, -1 },
- { "%Qi", "0x0", "0", 1, -1 },
- { "%Qi", "0x7b", "123", 1, -1 },
- { "%Qi", "0x7b", "123", 1, -1 },
- { "%Qi", "+0x0", "0", 1, -1 },
- { "%Qi", "+0x7b", "123", 1, -1 },
- { "%Qi", "+0x7b", "123", 1, -1 },
- { "%Qi", "-0x0", "-0", 1, -1 },
- { "%Qi", "-0x7b", "-123", 1, -1 },
- { "%Qi", "-0x7b", "-123", 1, -1 },
- { "%Qi", "0X0", "0", 1, -1 },
- { "%Qi", "0X7b", "123", 1, -1 },
- { "%Qi", "0X7b", "123", 1, -1 },
- { "%Qi", "+0X0", "0", 1, -1 },
- { "%Qi", "+0X7b", "123", 1, -1 },
- { "%Qi", "+0X7b", "123", 1, -1 },
- { "%Qi", "-0X0", "-0", 1, -1 },
- { "%Qi", "-0X7b", "-123", 1, -1 },
- { "%Qi", "-0X7b", "-123", 1, -1 },
- { "%Qi", "0x0", "0", 1, -1 },
- { "%Qi", "0x7B", "123", 1, -1 },
- { "%Qi", "0x7B", "123", 1, -1 },
- { "%Qi", "+0x0", "0", 1, -1 },
- { "%Qi", "+0x7B", "123", 1, -1 },
- { "%Qi", "+0x7B", "123", 1, -1 },
- { "%Qi", "-0x0", "-0", 1, -1 },
- { "%Qi", "-0x7B", "-123", 1, -1 },
- { "%Qi", "-0x7B", "-123", 1, -1 },
- { "%Qi", "0X0", "0", 1, -1 },
- { "%Qi", "0X7B", "123", 1, -1 },
- { "%Qi", "0X7B", "123", 1, -1 },
- { "%Qi", "+0X0", "0", 1, -1 },
- { "%Qi", "+0X7B", "123", 1, -1 },
- { "%Qi", "+0X7B", "123", 1, -1 },
- { "%Qi", "-0X0", "-0", 1, -1 },
- { "%Qi", "-0X7B", "-123", 1, -1 },
- { "%Qi", "-0X7B", "-123", 1, -1 },
- { "%Qd", " 0", "0", 1, -1 },
- { "%Qd", " 0", "0", 1, -1 },
- { "%Qd", " 0", "0", 1, -1 },
- { "%Qd", "t0", "0", 1, -1 },
- { "%Qd", "tt0", "0", 1, -1 },
- { "%Qd", "3/2", "3/2", 1, -1 },
- { "%Qd", "+3/2", "3/2", 1, -1 },
- { "%Qd", "-3/2", "-3/2", 1, -1 },
- { "%Qx", "f/10", "15/16", 1, -1 },
- { "%Qx", "F/10", "15/16", 1, -1 },
- { "%QX", "f/10", "15/16", 1, -1 },
- { "%QX", "F/10", "15/16", 1, -1 },
- { "%Qo", "20/21", "16/17", 1, -1 },
- { "%Qo", "-20/21", "-16/17", 1, -1 },
- { "%Qi", "10/11", "10/11", 1, -1 },
- { "%Qi", "+10/11", "10/11", 1, -1 },
- { "%Qi", "-10/11", "-10/11", 1, -1 },
- { "%Qi", "010/11", "8/11", 1, -1 },
- { "%Qi", "+010/11", "8/11", 1, -1 },
- { "%Qi", "-010/11", "-8/11", 1, -1 },
- { "%Qi", "0x10/11", "16/11", 1, -1 },
- { "%Qi", "+0x10/11", "16/11", 1, -1 },
- { "%Qi", "-0x10/11", "-16/11", 1, -1 },
- { "%Qi", "10/011", "10/9", 1, -1 },
- { "%Qi", "+10/011", "10/9", 1, -1 },
- { "%Qi", "-10/011", "-10/9", 1, -1 },
- { "%Qi", "010/011", "8/9", 1, -1 },
- { "%Qi", "+010/011", "8/9", 1, -1 },
- { "%Qi", "-010/011", "-8/9", 1, -1 },
- { "%Qi", "0x10/011", "16/9", 1, -1 },
- { "%Qi", "+0x10/011", "16/9", 1, -1 },
- { "%Qi", "-0x10/011", "-16/9", 1, -1 },
- { "%Qi", "10/0x11", "10/17", 1, -1 },
- { "%Qi", "+10/0x11", "10/17", 1, -1 },
- { "%Qi", "-10/0x11", "-10/17", 1, -1 },
- { "%Qi", "010/0x11", "8/17", 1, -1 },
- { "%Qi", "+010/0x11", "8/17", 1, -1 },
- { "%Qi", "-010/0x11", "-8/17", 1, -1 },
- { "%Qi", "0x10/0x11", "16/17", 1, -1 },
- { "%Qi", "+0x10/0x11", "16/17", 1, -1 },
- { "%Qi", "-0x10/0x11", "-16/17", 1, -1 },
- { "hello%Qd", "hello0", "0", 1, -1 },
- { "hello%Qd", "hello 0", "0", 1, -1 },
- { "hello%Qd", "hello t0", "0", 1, -1 },
- { "hello%Qdworld", "hello 0world", "0", 1, -1 },
- { "hello%Qd", "hello3/2", "3/2", 1, -1 },
- { "hello%*Qd", "hello0", "-999/121", 0, -1 },
- { "hello%*Qd", "hello 0", "-999/121", 0, -1 },
- { "hello%*Qd", "hello t0", "-999/121", 0, -1 },
- { "hello%*Qdworld", "hello 0world", "-999/121", 0, -1 },
- { "hello%*Qdworld", "hello3/2world", "-999/121", 0, -1 },
- { "%Qd", "", "-999/121", -1, -1 },
- { "%Qd", " ", "-999/121", -1, -1 },
- { " %Qd", "", "-999/121", -1, -1 },
- { "xyz%Qd", "", "-999/121", -1, -1 },
- { "%*Qd", "", "-999/121", -1, -1 },
- { " %*Qd", "", "-999/121", -1, -1 },
- { "xyz%*Qd", "", "-999/121", -1, -1 },
- /* match something, but invalid */
- { "%Qd", "-", "-999/121", 0, 1 },
- { "%Qd", "+", "-999/121", 0, 1 },
- { "%Qd", "/-", "-999/121", 0, 1 },
- { "%Qd", "/+", "-999/121", 0, 1 },
- { "%Qd", "-/", "-999/121", 0, 1 },
- { "%Qd", "+/", "-999/121", 0, 1 },
- { "%Qd", "-/-", "-999/121", 0, 1 },
- { "%Qd", "-/+", "-999/121", 0, 1 },
- { "%Qd", "+/+", "-999/121", 0, 1 },
- { "%Qd", "/123", "-999/121", 0, 1 },
- { "%Qd", "-/123", "-999/121", 0, 1 },
- { "%Qd", "+/123", "-999/121", 0, 1 },
- { "%Qd", "123/", "-999/121", 0, 1 },
- { "%Qd", "123/-", "-999/121", 0, 1 },
- { "%Qd", "123/+", "-999/121", 0, 1 },
- { "xyz%Qd", "xyz-", "-999/121", 0, 4 },
- { "xyz%Qd", "xyz+", "-999/121", 0, 4 },
- { "%1Qi", "12/57", "1", 1, 1 },
- { "%2Qi", "12/57", "12", 1, 2 },
- { "%3Qi", "12/57", "-999/121", 0, -1 },
- { "%4Qi", "12/57", "12/5", 1, 4 },
- { "%5Qi", "12/57", "12/57", 1, 5 },
- { "%6Qi", "12/57", "12/57", 1, 5 },
- { "%7Qi", "12/57", "12/57", 1, 5 },
- { "%1Qi", "012/057", "0", 1, 1 },
- { "%2Qi", "012/057", "01", 1, 2 },
- { "%3Qi", "012/057", "012", 1, 3 },
- { "%4Qi", "012/057", "-999/121", 0, -1 },
- { "%5Qi", "012/057", "012/0", 1, 5 },
- { "%6Qi", "012/057", "012/5", 1, 6 },
- { "%7Qi", "012/057", "012/057", 1, 7 },
- { "%8Qi", "012/057", "012/057", 1, 7 },
- { "%9Qi", "012/057", "012/057", 1, 7 },
- { "%1Qi", "0x12/0x57", "0", 1, 1 },
- { "%2Qi", "0x12/0x57", "-999", 0, 2 },
- { "%3Qi", "0x12/0x57", "0x1", 1, 3 },
- { "%4Qi", "0x12/0x57", "0x12", 1, 4 },
- { "%5Qi", "0x12/0x57", "-999/121", 0, 5 },
- { "%6Qi", "0x12/0x57", "0x12/0", 1, 6 },
- { "%7Qi", "0x12/0x57", "-999/121", 0, 7 },
- { "%8Qi", "0x12/0x57", "0x12/0x5", 1, 8 },
- { "%9Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
- { "%10Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
- { "%11Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
- { "%Qd", "xyz", "0", 0, 0 },
- };
- int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
- mpq_t got, want;
- long got_l, want_ftell;
- int error = 0;
- fun_t fun;
- const char *name;
- char fmt[128];
- mpq_init (got);
- mpq_init (want);
- for (i = 0; i < numberof (data); i++)
- {
- mpq_set_str_or_abort (want, data[i].want, 0);
- ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
- strcpy (fmt, data[i].fmt);
- strcat (fmt, "%n");
- ignore = (strchr (fmt, '*') != NULL);
- for (j = 0; j <= 3; j++)
- {
- want_ret = data[i].ret;
- want_ftell = data[i].ftell;
- if (want_ftell == -1)
- want_ftell = strlen (data[i].input);
- want_upto = want_ftell;
- if (want_ret == -1 || (want_ret == 0 && ! ignore))
- {
- want_ftell = -1;
- want_upto = -555;
- }
- switch (j) {
- case 0:
- name = "gmp_sscanf";
- fun = fun_gmp_sscanf;
- break;
- case 1:
- name = "gmp_fscanf";
- fun = fun_gmp_fscanf;
- break;
- case 2:
- if (strchr (data[i].input, '/') != NULL)
- continue;
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard sscanf";
- fun = fun_sscanf;
- break;
- case 3:
- if (strchr (data[i].input, '/') != NULL)
- continue;
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard fscanf";
- fun = fun_fscanf;
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- got_upto = -555;
- got_ftell = -1;
- switch (j) {
- case 0:
- case 1:
- mpq_set_si (got, -999L, 121L);
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
- break;
- case 2:
- case 3:
- got_l = -999L;
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
- mpq_set_si (got, got_l, (got_l == -999L ? 121L : 1L));
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- MPZ_CHECK_FORMAT (mpq_numref (got));
- MPZ_CHECK_FORMAT (mpq_denref (got));
- if (got_ret != want_ret)
- {
- printf ("%s wrong return valuen", name);
- error = 1;
- }
- /* use direct mpz compares, since some of the test data is
- non-canonical and can trip ASSERTs in mpq_equal */
- if (want_ret == 1
- && ! (mpz_cmp (mpq_numref(want), mpq_numref(got)) == 0
- && mpz_cmp (mpq_denref(want), mpq_denref(got)) == 0))
- {
- printf ("%s wrong resultn", name);
- error = 1;
- }
- if (got_upto != want_upto)
- {
- printf ("%s wrong upton", name);
- error = 1;
- }
- if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
- {
- printf ("%s wrong ftelln", name);
- error = 1;
- }
- if (error)
- {
- printf (" fmt "%s"n", data[i].fmt);
- printf (" input "%s"n", data[i].input);
- printf (" ret want=%dn", want_ret);
- printf (" got =%dn", got_ret);
- mpq_trace (" value want", want);
- mpq_trace (" got ", got);
- printf (" upto want=%dn", want_upto);
- printf (" got =%dn", got_upto);
- if (got_ftell != -1)
- {
- printf (" ftell want =%ldn", want_ftell);
- printf (" got =%ldn", got_ftell);
- }
- abort ();
- }
- }
- }
- mpq_clear (got);
- mpq_clear (want);
- }
- void
- check_f (void)
- {
- static const struct {
- const char *fmt;
- const char *input;
- const char *want;
- int ret;
- long ftell; /* or -1 for length of input string */
- } data[] = {
- { "%Ff", "0", "0", 1, -1 },
- { "%Fe", "0", "0", 1, -1 },
- { "%FE", "0", "0", 1, -1 },
- { "%Fg", "0", "0", 1, -1 },
- { "%FG", "0", "0", 1, -1 },
- { "%Ff", "123", "123", 1, -1 },
- { "%Ff", "+123", "123", 1, -1 },
- { "%Ff", "-123", "-123", 1, -1 },
- { "%Ff", "123.", "123", 1, -1 },
- { "%Ff", "+123.", "123", 1, -1 },
- { "%Ff", "-123.", "-123", 1, -1 },
- { "%Ff", "123.0", "123", 1, -1 },
- { "%Ff", "+123.0", "123", 1, -1 },
- { "%Ff", "-123.0", "-123", 1, -1 },
- { "%Ff", "0123", "123", 1, -1 },
- { "%Ff", "-0123", "-123", 1, -1 },
- { "%Ff", "123.456e3", "123456", 1, -1 },
- { "%Ff", "-123.456e3", "-123456", 1, -1 },
- { "%Ff", "123.456e+3", "123456", 1, -1 },
- { "%Ff", "-123.456e+3", "-123456", 1, -1 },
- { "%Ff", "123000e-3", "123", 1, -1 },
- { "%Ff", "-123000e-3", "-123", 1, -1 },
- { "%Ff", "123000.e-3", "123", 1, -1 },
- { "%Ff", "-123000.e-3", "-123", 1, -1 },
- { "%Ff", "123.456E3", "123456", 1, -1 },
- { "%Ff", "-123.456E3", "-123456", 1, -1 },
- { "%Ff", "123.456E+3", "123456", 1, -1 },
- { "%Ff", "-123.456E+3", "-123456", 1, -1 },
- { "%Ff", "123000E-3", "123", 1, -1 },
- { "%Ff", "-123000E-3", "-123", 1, -1 },
- { "%Ff", "123000.E-3", "123", 1, -1 },
- { "%Ff", "-123000.E-3", "-123", 1, -1 },
- { "%Ff", ".456e3", "456", 1, -1 },
- { "%Ff", "-.456e3", "-456", 1, -1 },
- { "%Ff", ".456e+3", "456", 1, -1 },
- { "%Ff", "-.456e+3", "-456", 1, -1 },
- { "%Ff", " 0", "0", 1, -1 },
- { "%Ff", " 0", "0", 1, -1 },
- { "%Ff", " 0", "0", 1, -1 },
- { "%Ff", "t0", "0", 1, -1 },
- { "%Ff", "tt0", "0", 1, -1 },
- { "hello%Fg", "hello0", "0", 1, -1 },
- { "hello%Fg", "hello 0", "0", 1, -1 },
- { "hello%Fg", "hello t0", "0", 1, -1 },
- { "hello%Fgworld", "hello 0world", "0", 1, -1 },
- { "hello%Fg", "hello3.0", "3.0", 1, -1 },
- { "hello%*Fg", "hello0", "-999", 0, -1 },
- { "hello%*Fg", "hello 0", "-999", 0, -1 },
- { "hello%*Fg", "hello t0", "-999", 0, -1 },
- { "hello%*Fgworld", "hello 0world", "-999", 0, -1 },
- { "hello%*Fgworld", "hello3.0world", "-999", 0, -1 },
- { "%Ff", "", "-999", -1, -1 },
- { "%Ff", " ", "-999", -1, -1 },
- { "%Ff", "t", "-999", -1, -1 },
- { "%Ff", " t", "-999", -1, -1 },
- { " %Ff", "", "-999", -1, -1 },
- { "xyz%Ff", "", "-999", -1, -1 },
- { "%*Ff", "", "-999", -1, -1 },
- { " %*Ff", "", "-999", -1, -1 },
- { "xyz%*Ff", "", "-999", -1, -1 },
- { "%Ff", "xyz", "0", 0 },
- /* various non-empty but invalid */
- { "%Ff", "-", "-999", 0, 1 },
- { "%Ff", "+", "-999", 0, 1 },
- { "xyz%Ff", "xyz-", "-999", 0, 4 },
- { "xyz%Ff", "xyz+", "-999", 0, 4 },
- { "%Ff", "-.", "-999", 0, 2 },
- { "%Ff", "+.", "-999", 0, 2 },
- { "%Ff", ".e", "-999", 0, 1 },
- { "%Ff", "-.e", "-999", 0, 2 },
- { "%Ff", "+.e", "-999", 0, 2 },
- { "%Ff", ".E", "-999", 0, 1 },
- { "%Ff", "-.E", "-999", 0, 2 },
- { "%Ff", "+.E", "-999", 0, 2 },
- { "%Ff", ".e123", "-999", 0, 1 },
- { "%Ff", "-.e123", "-999", 0, 2 },
- { "%Ff", "+.e123", "-999", 0, 2 },
- { "%Ff", "123e", "-999", 0, 4 },
- { "%Ff", "-123e", "-999", 0, 5 },
- { "%Ff", "123e-", "-999", 0, 5 },
- { "%Ff", "-123e-", "-999", 0, 6 },
- { "%Ff", "123e+", "-999", 0, 5 },
- { "%Ff", "-123e+", "-999", 0, 6 },
- { "%Ff", "123e-Z", "-999", 0, 5 },
- /* hex floats */
- { "%Ff", "0x123p0", "291", 1, -1 },
- { "%Ff", "0x123P0", "291", 1, -1 },
- { "%Ff", "0X123p0", "291", 1, -1 },
- { "%Ff", "0X123P0", "291", 1, -1 },
- { "%Ff", "-0x123p0", "-291", 1, -1 },
- { "%Ff", "+0x123p0", "291", 1, -1 },
- { "%Ff", "0x123.p0", "291", 1, -1 },
- { "%Ff", "0x12.3p4", "291", 1, -1 },
- { "%Ff", "-0x12.3p4", "-291", 1, -1 },
- { "%Ff", "+0x12.3p4", "291", 1, -1 },
- { "%Ff", "0x1230p-4", "291", 1, -1 },
- { "%Ff", "-0x1230p-4", "-291", 1, -1 },
- { "%Ff", "+0x1230p-4", "291", 1, -1 },
- { "%Ff", "+0x.1230p12", "291", 1, -1 },
- { "%Ff", "+0x123000p-12", "291", 1, -1 },
- { "%Ff", "0x123 p12", "291", 1, 5 },
- { "%Ff", "0x9 9", "9", 1, 3 },
- { "%Ff", "0x01", "1", 1, 4 },
- { "%Ff", "0x23", "35", 1, 4 },
- { "%Ff", "0x45", "69", 1, 4 },
- { "%Ff", "0x67", "103", 1, 4 },
- { "%Ff", "0x89", "137", 1, 4 },
- { "%Ff", "0xAB", "171", 1, 4 },
- { "%Ff", "0xCD", "205", 1, 4 },
- { "%Ff", "0xEF", "239", 1, 4 },
- { "%Ff", "0xab", "171", 1, 4 },
- { "%Ff", "0xcd", "205", 1, 4 },
- { "%Ff", "0xef", "239", 1, 4 },
- { "%Ff", "0x100p0A", "256", 1, 7 },
- { "%Ff", "0x1p9", "512", 1, -1 },
- /* invalid hex floats */
- { "%Ff", "0x", "-999", 0, 2 },
- { "%Ff", "-0x", "-999", 0, 3 },
- { "%Ff", "+0x", "-999", 0, 3 },
- { "%Ff", "0x-", "-999", 0, 2 },
- { "%Ff", "0x+", "-999", 0, 2 },
- { "%Ff", "0x.", "-999", 0, 3 },
- { "%Ff", "-0x.", "-999", 0, 4 },
- { "%Ff", "+0x.", "-999", 0, 4 },
- { "%Ff", "0x.p", "-999", 0, 3 },
- { "%Ff", "-0x.p", "-999", 0, 4 },
- { "%Ff", "+0x.p", "-999", 0, 4 },
- { "%Ff", "0x.P", "-999", 0, 3 },
- { "%Ff", "-0x.P", "-999", 0, 4 },
- { "%Ff", "+0x.P", "-999", 0, 4 },
- { "%Ff", ".p123", "-999", 0, 1 },
- { "%Ff", "-.p123", "-999", 0, 2 },
- { "%Ff", "+.p123", "-999", 0, 2 },
- { "%Ff", "0x1p", "-999", 0, 4 },
- { "%Ff", "0x1p-", "-999", 0, 5 },
- { "%Ff", "0x1p+", "-999", 0, 5 },
- { "%Ff", "0x123p 12", "291", 0, 6 },
- { "%Ff", "0x 123p12", "291", 0, 2 },
- };
- int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
- mpf_t got, want;
- double got_d;
- long want_ftell;
- int error = 0;
- fun_t fun;
- const char *name;
- char fmt[128];
- mpf_init (got);
- mpf_init (want);
- for (i = 0; i < numberof (data); i++)
- {
- mpf_set_str_or_abort (want, data[i].want, 10);
- ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
- strcpy (fmt, data[i].fmt);
- strcat (fmt, "%n");
- ignore = (strchr (fmt, '*') != NULL);
- for (j = 0; j <= 3; j++)
- {
- want_ret = data[i].ret;
- want_ftell = data[i].ftell;
- if (want_ftell == -1)
- want_ftell = strlen (data[i].input);
- want_upto = want_ftell;
- if (want_ret == -1 || (want_ret == 0 && ! ignore))
- want_upto = -555;
- switch (j) {
- case 0:
- name = "gmp_sscanf";
- fun = fun_gmp_sscanf;
- break;
- case 1:
- name = "gmp_fscanf";
- fun = fun_gmp_fscanf;
- break;
- case 2:
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard sscanf";
- fun = fun_sscanf;
- break;
- case 3:
- if (! libc_scanf_convert (fmt))
- continue;
- name = "standard fscanf";
- fun = fun_fscanf;
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- got_upto = -555;
- got_ftell = -1;
- switch (j) {
- case 0:
- case 1:
- mpf_set_si (got, -999L);
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
- break;
- case 2:
- case 3:
- got_d = -999L;
- if (ignore)
- got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
- else
- got_ret = (*fun) (data[i].input, fmt, &got_d, &got_upto);
- mpf_set_d (got, got_d);
- break;
- default:
- ASSERT_ALWAYS (0);
- break;
- }
- MPF_CHECK_FORMAT (got);
- if (got_ret != want_ret)
- {
- printf ("%s wrong return valuen", name);
- error = 1;
- }
- if (want_ret == 1 && mpf_cmp (want, got) != 0)
- {
- printf ("%s wrong resultn", name);
- error = 1;
- }
- if (got_upto != want_upto)
- {
- printf ("%s wrong upton", name);
- error = 1;
- }
- if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
- {
- printf ("%s wrong ftelln", name);
- error = 1;
- }
- if (error)
- {
- printf (" fmt "%s"n", data[i].fmt);
- printf (" input "%s"n", data[i].input);
- printf (" ret want=%dn", want_ret);
- printf (" got =%dn", got_ret);
- mpf_trace (" value want", want);
- mpf_trace (" got ", got);
- printf (" upto want=%dn", want_upto);
- printf (" got =%dn", got_upto);
- if (got_ftell != -1)
- {
- printf (" ftell want =%ldn", want_ftell);
- printf (" got =%ldn", got_ftell);
- }
- abort ();
- }
- }
- }
- mpf_clear (got);
- mpf_clear (want);
- }
- void
- check_n (void)
- {
- int ret;
- /* %n suppressed */
- {
- int n = 123;
- gmp_sscanf (" ", " %*n", &n);
- ASSERT_ALWAYS (n == 123);
- }
- {
- int n = 123;
- fromstring_gmp_fscanf (" ", " %*n", &n);
- ASSERT_ALWAYS (n == 123);
- }
- #define CHECK_N(type, string)
- do {
- type x[2];
- char fmt[128];
- int ret;
-
- x[0] = ~ (type) 0;
- x[1] = ~ (type) 0;
- sprintf (fmt, "abc%%%sn", string);
- ret = gmp_sscanf ("abc", fmt, &x[0]);
-
- ASSERT_ALWAYS (ret == 0);
-
- /* should write whole of x[0] and none of x[1] */
- ASSERT_ALWAYS (x[0] == 3);
- ASSERT_ALWAYS (x[1] == (type) ~ (type) 0);
-
- } while (0)
- CHECK_N (char, "hh");
- CHECK_N (long, "l");
- #if HAVE_LONG_LONG
- CHECK_N (long long, "L");
- #endif
- #if HAVE_INTMAX_T
- CHECK_N (intmax_t, "j");
- #endif
- #if HAVE_PTRDIFF_T
- CHECK_N (ptrdiff_t, "t");
- #endif
- CHECK_N (short, "h");
- CHECK_N (size_t, "z");
- /* %Zn */
- {
- mpz_t x[2];
- mpz_init_set_si (x[0], -987L);
- mpz_init_set_si (x[1], 654L);
- ret = gmp_sscanf ("xyz ", "xyz%Zn", x[0]);
- MPZ_CHECK_FORMAT (x[0]);
- MPZ_CHECK_FORMAT (x[1]);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
- ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
- mpz_clear (x[0]);
- mpz_clear (x[1]);
- }
- {
- mpz_t x;
- mpz_init (x);
- ret = fromstring_gmp_fscanf ("xyz ", "xyz%Zn", x);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpz_cmp_ui (x, 3L) == 0);
- mpz_clear (x);
- }
- /* %Qn */
- {
- mpq_t x[2];
- mpq_init (x[0]);
- mpq_init (x[1]);
- mpq_set_ui (x[0], 987L, 654L);
- mpq_set_ui (x[1], 4115L, 226L);
- ret = gmp_sscanf ("xyz ", "xyz%Qn", x[0]);
- MPQ_CHECK_FORMAT (x[0]);
- MPQ_CHECK_FORMAT (x[1]);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
- ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
- mpq_clear (x[0]);
- mpq_clear (x[1]);
- }
- {
- mpq_t x;
- mpq_init (x);
- ret = fromstring_gmp_fscanf ("xyz ", "xyz%Qn", x);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpq_cmp_ui (x, 3L, 1L) == 0);
- mpq_clear (x);
- }
- /* %Fn */
- {
- mpf_t x[2];
- mpf_init (x[0]);
- mpf_init (x[1]);
- mpf_set_ui (x[0], 987L);
- mpf_set_ui (x[1], 654L);
- ret = gmp_sscanf ("xyz ", "xyz%Fn", x[0]);
- MPF_CHECK_FORMAT (x[0]);
- MPF_CHECK_FORMAT (x[1]);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
- ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
- mpf_clear (x[0]);
- mpf_clear (x[1]);
- }
- {
- mpf_t x;
- mpf_init (x);
- ret = fromstring_gmp_fscanf ("xyz ", "xyz%Fn", x);
- ASSERT_ALWAYS (ret == 0);
- ASSERT_ALWAYS (mpf_cmp_ui (x, 3L) == 0);
- mpf_clear (x);
- }
- }
- void
- check_misc (void)
- {
- int ret, cmp;
- {
- int a=9, b=8, c=7, n=66;
- mpz_t z;
- mpz_init (z);
- ret = gmp_sscanf ("1 2 3 4", "%d %d %d %Zd%n",
- &a, &b, &c, z, &n);
- ASSERT_ALWAYS (ret == 4);
- ASSERT_ALWAYS (a == 1);
- ASSERT_ALWAYS (b == 2);
- ASSERT_ALWAYS (c == 3);
- ASSERT_ALWAYS (n == 7);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
- mpz_clear (z);
- }
- {
- int a=9, b=8, c=7, n=66;
- mpz_t z;
- mpz_init (z);
- ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %d %d %Zd%n",
- &a, &b, &c, z, &n);
- ASSERT_ALWAYS (ret == 4);
- ASSERT_ALWAYS (a == 1);
- ASSERT_ALWAYS (b == 2);
- ASSERT_ALWAYS (c == 3);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
- ASSERT_ALWAYS (n == 7);
- ASSERT_ALWAYS (got_ftell == 7);
- mpz_clear (z);
- }
- {
- int a=9, n=8;
- mpz_t z;
- mpz_init (z);
- ret = gmp_sscanf ("1 2 3 4", "%d %*d %*d %Zd%n", &a, z, &n);
- ASSERT_ALWAYS (ret == 2);
- ASSERT_ALWAYS (a == 1);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
- ASSERT_ALWAYS (n == 7);
- mpz_clear (z);
- }
- {
- int a=9, n=8;
- mpz_t z;
- mpz_init (z);
- ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %*d %*d %Zd%n",
- &a, z, &n);
- ASSERT_ALWAYS (ret == 2);
- ASSERT_ALWAYS (a == 1);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
- ASSERT_ALWAYS (n == 7);
- ASSERT_ALWAYS (got_ftell == 7);
- mpz_clear (z);
- }
- /* EOF for no matching */
- {
- char buf[128];
- ret = gmp_sscanf (" ", "%s", buf);
- ASSERT_ALWAYS (ret == EOF);
- ret = fromstring_gmp_fscanf (" ", "%s", buf);
- ASSERT_ALWAYS (ret == EOF);
- if (option_libc_scanf)
- {
- ret = sscanf (" ", "%s", buf);
- ASSERT_ALWAYS (ret == EOF);
- ret = fun_fscanf (" ", "%s", buf, NULL);
- ASSERT_ALWAYS (ret == EOF);
- }
- }
- /* suppressed field, then eof */
- {
- int x;
- if (test_sscanf_eof_ok ())
- {
- ret = gmp_sscanf ("123", "%*d%d", &x);
- ASSERT_ALWAYS (ret == EOF);
- }
- ret = fromstring_gmp_fscanf ("123", "%*d%d", &x);
- ASSERT_ALWAYS (ret == EOF);
- if (option_libc_scanf)
- {
- ret = sscanf ("123", "%*d%d", &x);
- ASSERT_ALWAYS (ret == EOF);
- ret = fun_fscanf ("123", "%*d%d", &x, NULL);
- ASSERT_ALWAYS (ret == EOF);
- }
- }
- {
- mpz_t x;
- mpz_init (x);
- ret = gmp_sscanf ("123", "%*Zd%Zd", x);
- ASSERT_ALWAYS (ret == EOF);
- ret = fromstring_gmp_fscanf ("123", "%*Zd%Zd", x);
- ASSERT_ALWAYS (ret == EOF);
- mpz_clear (x);
- }
- /* %[...], glibc only */
- #ifdef __GLIBC__
- {
- char buf[128];
- int n = -1;
- buf[0] = ' ';
- ret = gmp_sscanf ("abcdefgh", "%[a-d]ef%n", buf, &n);
- ASSERT_ALWAYS (ret == 1);
- cmp = strcmp (buf, "abcd");
- ASSERT_ALWAYS (cmp == 0);
- ASSERT_ALWAYS (n == 6);
- }
- {
- char buf[128];
- int n = -1;
- buf[0] = ' ';
- ret = gmp_sscanf ("xyza", "%[^a]a%n", buf, &n);
- ASSERT_ALWAYS (ret == 1);
- cmp = strcmp (buf, "xyz");
- ASSERT_ALWAYS (cmp == 0);
- ASSERT_ALWAYS (n == 4);
- }
- {
- char buf[128];
- int n = -1;
- buf[0] = ' ';
- ret = gmp_sscanf ("ab]ab]", "%[]ab]%n", buf, &n);
- ASSERT_ALWAYS (ret == 1);
- cmp = strcmp (buf, "ab]ab]");
- ASSERT_ALWAYS (cmp == 0);
- ASSERT_ALWAYS (n == 6);
- }
- {
- char buf[128];
- int n = -1;
- buf[0] = ' ';
- ret = gmp_sscanf ("xyzb", "%[^]ab]b%n", buf, &n);
- ASSERT_ALWAYS (ret == 1);
- cmp = strcmp (buf, "xyz");
- ASSERT_ALWAYS (cmp == 0);
- ASSERT_ALWAYS (n == 4);
- }
- #endif
- /* %zd etc won't be accepted by sscanf on old systems, and running
- something to see if they work might be bad, so only try it on glibc,
- and only on a new enough version (glibc 2.0 doesn't have %zd) */
- #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
- {
- mpz_t z;
- size_t s = -1;
- mpz_init (z);
- ret = gmp_sscanf ("456 789", "%zd %Zd", &s, z);
- ASSERT_ALWAYS (ret == 2);
- ASSERT_ALWAYS (s == 456);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
- mpz_clear (z);
- }
- {
- mpz_t z;
- ptrdiff_t d = -1;
- mpz_init (z);
- ret = gmp_sscanf ("456 789", "%td %Zd", &d, z);
- ASSERT_ALWAYS (ret == 2);
- ASSERT_ALWAYS (d == 456);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
- mpz_clear (z);
- }
- {
- mpz_t z;
- long long ll = -1;
- mpz_init (z);
- ret = gmp_sscanf ("456 789", "%Ld %Zd", &ll, z);
- ASSERT_ALWAYS (ret == 2);
- ASSERT_ALWAYS (ll == 456);
- ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
- mpz_clear (z);
- }
- #endif
- }
- int
- main (int argc, char *argv[])
- {
- if (argc > 1 && strcmp (argv[1], "-s") == 0)
- option_libc_scanf = 1;
- tests_start ();
- mp_trace_base = 16;
- check_z ();
- check_q ();
- check_f ();
- check_n ();
- check_misc ();
- unlink (TEMPFILE);
- tests_end ();
- exit (0);
- }