github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/misc/t-scanf.c (about)

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