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