t-scanf.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:49k
源码类别:

数学计算

开发平台:

Unix_Linux

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