1636 lines
49 KiB
C
1636 lines
49 KiB
C
/* 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 2.1 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; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
|
|
/* 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 "mpir.h"
|
|
#include "gmp-impl.h"
|
|
#include "tests.h"
|
|
|
|
|
|
#define TEMPFILE "t-scanf.tmp"
|
|
|
|
int option_libc_scanf = 0;
|
|
|
|
typedef int (*fun_t)(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 != '\0'; fmt++)
|
|
{
|
|
switch (*fmt) {
|
|
case 'F':
|
|
case 'Q':
|
|
case 'Z':
|
|
/* transmute */
|
|
*p++ = 'l';
|
|
break;
|
|
default:
|
|
*p++ = *fmt;
|
|
break;
|
|
}
|
|
}
|
|
*p = '\0';
|
|
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 != '\0'; 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", "\t\t0", "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 value\n", name);
|
|
error = 1;
|
|
}
|
|
if (want_ret == 1 && mpz_cmp (want, got) != 0)
|
|
{
|
|
printf ("%s wrong result\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_upto != want_upto)
|
|
{
|
|
printf ("%s wrong upto\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
|
|
{
|
|
printf ("%s wrong ftell\n", name);
|
|
error = 1;
|
|
}
|
|
if (error)
|
|
{
|
|
printf (" fmt \"%s\"\n", data[i].fmt);
|
|
printf (" input \"%s\"\n", data[i].input);
|
|
printf (" ignore %d\n", ignore);
|
|
printf (" ret want=%d\n", want_ret);
|
|
printf (" got =%d\n", got_ret);
|
|
mpz_trace (" value want", want);
|
|
mpz_trace (" got ", got);
|
|
printf (" upto want =%d\n", want_upto);
|
|
printf (" got =%d\n", got_upto);
|
|
if (got_ftell != -1)
|
|
{
|
|
printf (" ftell want =%ld\n", want_ftell);
|
|
printf (" got =%ld\n", 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", "\t\t0", "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 value\n", 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 result\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_upto != want_upto)
|
|
{
|
|
printf ("%s wrong upto\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
|
|
{
|
|
printf ("%s wrong ftell\n", name);
|
|
error = 1;
|
|
}
|
|
if (error)
|
|
{
|
|
printf (" fmt \"%s\"\n", data[i].fmt);
|
|
printf (" input \"%s\"\n", data[i].input);
|
|
printf (" ret want=%d\n", want_ret);
|
|
printf (" got =%d\n", got_ret);
|
|
mpq_trace (" value want", want);
|
|
mpq_trace (" got ", got);
|
|
printf (" upto want=%d\n", want_upto);
|
|
printf (" got =%d\n", got_upto);
|
|
if (got_ftell != -1)
|
|
{
|
|
printf (" ftell want =%ld\n", want_ftell);
|
|
printf (" got =%ld\n", 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", "\t\t0", "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 value\n", name);
|
|
error = 1;
|
|
}
|
|
if (want_ret == 1 && mpf_cmp (want, got) != 0)
|
|
{
|
|
printf ("%s wrong result\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_upto != want_upto)
|
|
{
|
|
printf ("%s wrong upto\n", name);
|
|
error = 1;
|
|
}
|
|
if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
|
|
{
|
|
printf ("%s wrong ftell\n", name);
|
|
error = 1;
|
|
}
|
|
if (error)
|
|
{
|
|
printf (" fmt \"%s\"\n", data[i].fmt);
|
|
printf (" input \"%s\"\n", data[i].input);
|
|
printf (" ret want=%d\n", want_ret);
|
|
printf (" got =%d\n", got_ret);
|
|
mpf_trace (" value want", want);
|
|
mpf_trace (" got ", got);
|
|
printf (" upto want=%d\n", want_upto);
|
|
printf (" got =%d\n", got_upto);
|
|
if (got_ftell != -1)
|
|
{
|
|
printf (" ftell want =%ld\n", want_ftell);
|
|
printf (" got =%ld\n", 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
|
|
CHECK_N (ptrdiff_t, "t");
|
|
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] = '\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] = '\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] = '\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] = '\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);
|
|
}
|