[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     ! 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>