[BACK]Return to t-scanf.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / tests / misc

Annotation of OpenXM_contrib/gmp/tests/misc/t-scanf.c, Revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>