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

Annotation of OpenXM_contrib/gmp/tests/misc/t-printf.c, Revision 1.1

1.1     ! ohara       1: /* Test gmp_printf 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-printf [-s]
        !            24:
        !            25:    -s  Check the data against the system printf, where possible.  This is
        !            26:        only an option since we don't want to fail if the system printf is
        !            27:        faulty or strange.  */
        !            28:
        !            29:
        !            30: #include "config.h"
        !            31:
        !            32: #if HAVE_STDARG
        !            33: #include <stdarg.h>
        !            34: #else
        !            35: #include <varargs.h>
        !            36: #endif
        !            37:
        !            38: #include <stddef.h>    /* for ptrdiff_t */
        !            39: #include <stdio.h>
        !            40: #include <stdlib.h>
        !            41: #include <string.h>
        !            42:
        !            43: #if HAVE_OBSTACK_VPRINTF
        !            44: #define obstack_chunk_alloc tests_allocate
        !            45: #define obstack_chunk_free  tests_free_nosize
        !            46: #include <obstack.h>
        !            47: #endif
        !            48:
        !            49: #if HAVE_INTTYPES_H
        !            50: # include <inttypes.h> /* for intmax_t */
        !            51: #else
        !            52: # if HAVE_STDINT_H
        !            53: #  include <stdint.h>
        !            54: # endif
        !            55: #endif
        !            56:
        !            57: #if HAVE_UNISTD_H
        !            58: #include <unistd.h>  /* for unlink */
        !            59: #endif
        !            60:
        !            61: #include "gmp.h"
        !            62: #include "gmp-impl.h"
        !            63: #include "tests.h"
        !            64:
        !            65:
        !            66: int   option_check_printf = 0;
        !            67:
        !            68:
        !            69: #define CHECK_VFPRINTF_FILENAME  "t-printf.tmp"
        !            70: FILE  *check_vfprintf_fp;
        !            71:
        !            72:
        !            73: /* From any of the tests run here. */
        !            74: #define MAX_OUTPUT  1024
        !            75:
        !            76:
        !            77: void
        !            78: #if HAVE_STDARG
        !            79: check_plain (const char *want, const char *fmt_orig, ...)
        !            80: #else
        !            81: check_plain (va_alist)
        !            82:      va_dcl
        !            83: #endif
        !            84: {
        !            85:   char        got[MAX_OUTPUT];
        !            86:   int         got_len, want_len;
        !            87:   size_t      fmtsize;
        !            88:   char        *fmt, *q;
        !            89:   const char  *p;
        !            90:   va_list     ap;
        !            91: #if HAVE_STDARG
        !            92:   va_start (ap, fmt_orig);
        !            93: #else
        !            94:   const char  *want;
        !            95:   const char  *fmt_orig;
        !            96:   va_start (ap);
        !            97:   want = va_arg (ap, const char *);
        !            98:   fmt_orig = va_arg (ap, const char *);
        !            99: #endif
        !           100:
        !           101:   if (! option_check_printf)
        !           102:     return;
        !           103:
        !           104:   fmtsize = strlen (fmt_orig) + 1;
        !           105:   fmt = (*__gmp_allocate_func) (fmtsize);
        !           106:
        !           107:   for (p = fmt_orig, q = fmt; *p != '\0'; p++)
        !           108:     {
        !           109:       switch (*p) {
        !           110:       case 'a':
        !           111:       case 'A':
        !           112:         /* The exact value of the exponent isn't guaranteed in glibc, and it
        !           113:            and gmp_printf do slightly different things, so don't compare
        !           114:            directly. */
        !           115:         goto done;
        !           116:       case 'F':
        !           117:         if (p > fmt_orig && *(p-1) == '.')
        !           118:           goto done;  /* don't test the "all digits" cases */
        !           119:         /* discard 'F' type */
        !           120:         break;
        !           121:       case 'Z':
        !           122:         /* transmute */
        !           123:         *q++ = 'l';
        !           124:         break;
        !           125:       default:
        !           126:         *q++ = *p;
        !           127:         break;
        !           128:       }
        !           129:     }
        !           130:   *q = '\0';
        !           131:
        !           132:   want_len = strlen (want);
        !           133:   ASSERT_ALWAYS (want_len < sizeof(got));
        !           134:
        !           135:   got_len = vsprintf (got, fmt, ap);
        !           136:
        !           137:   if (got_len != want_len || strcmp (got, want) != 0)
        !           138:     {
        !           139:       printf ("wanted data doesn't match plain vsprintf\n");
        !           140:       printf ("  fmt      |%s|\n", fmt);
        !           141:       printf ("  got      |%s|\n", got);
        !           142:       printf ("  want     |%s|\n", want);
        !           143:       printf ("  got_len  %d\n", got_len);
        !           144:       printf ("  want_len %d\n", want_len);
        !           145:       abort ();
        !           146:     }
        !           147:
        !           148:  done:
        !           149:   (*__gmp_free_func) (fmt, fmtsize);
        !           150: }
        !           151:
        !           152: void
        !           153: check_vsprintf (const char *want, const char *fmt, va_list ap)
        !           154: {
        !           155:   char  got[MAX_OUTPUT];
        !           156:   int   got_len, want_len;
        !           157:
        !           158:   want_len = strlen (want);
        !           159:   got_len = gmp_vsprintf (got, fmt, ap);
        !           160:
        !           161:   if (got_len != want_len || strcmp (got, want) != 0)
        !           162:     {
        !           163:       printf ("gmp_vsprintf wrong\n");
        !           164:       printf ("  fmt      |%s|\n", fmt);
        !           165:       printf ("  got      |%s|\n", got);
        !           166:       printf ("  want     |%s|\n", want);
        !           167:       printf ("  got_len  %d\n", got_len);
        !           168:       printf ("  want_len %d\n", want_len);
        !           169:       abort ();
        !           170:     }
        !           171: }
        !           172:
        !           173: void
        !           174: check_vfprintf (const char *want, const char *fmt, va_list ap)
        !           175: {
        !           176:   char  got[MAX_OUTPUT];
        !           177:   int   got_len, want_len, fread_len;
        !           178:   long  ftell_len;
        !           179:
        !           180:   want_len = strlen (want);
        !           181:
        !           182:   rewind (check_vfprintf_fp);
        !           183:   got_len = gmp_vfprintf (check_vfprintf_fp, fmt, ap);
        !           184:   ASSERT_ALWAYS (got_len != -1);
        !           185:   ASSERT_ALWAYS (fflush (check_vfprintf_fp) == 0);
        !           186:
        !           187:   ftell_len = ftell (check_vfprintf_fp);
        !           188:   ASSERT_ALWAYS (ftell_len != -1);
        !           189:
        !           190:   rewind (check_vfprintf_fp);
        !           191:   ASSERT_ALWAYS (ftell_len <= sizeof(got));
        !           192:   fread_len = fread (got, 1, ftell_len, check_vfprintf_fp);
        !           193:
        !           194:   if (got_len != want_len
        !           195:       || ftell_len != want_len
        !           196:       || fread_len != want_len
        !           197:       || memcmp (got, want, want_len) != 0)
        !           198:     {
        !           199:       printf ("gmp_vfprintf wrong\n");
        !           200:       printf ("  fmt       |%s|\n", fmt);
        !           201:       printf ("  got       |%.*s|\n", fread_len, got);
        !           202:       printf ("  want      |%s|\n", want);
        !           203:       printf ("  got_len   %d\n", got_len);
        !           204:       printf ("  ftell_len %ld\n", ftell_len);
        !           205:       printf ("  fread_len %d\n", fread_len);
        !           206:       printf ("  want_len  %d\n", want_len);
        !           207:       abort ();
        !           208:     }
        !           209: }
        !           210:
        !           211: void
        !           212: check_vsnprintf (const char *want, const char *fmt, va_list ap)
        !           213: {
        !           214:   char    got[MAX_OUTPUT+1];
        !           215:   int     ret, got_len, want_len;
        !           216:   size_t  bufsize;
        !           217:
        !           218:   want_len = strlen (want);
        !           219:
        !           220:   bufsize = -1;
        !           221:   for (;;)
        !           222:     {
        !           223:       /* do 0 to 5, then want-5 to want+5 */
        !           224:       bufsize++;
        !           225:       if (bufsize > 5 && bufsize < want_len-5)
        !           226:         bufsize = want_len-5;
        !           227:       if (bufsize > want_len + 5)
        !           228:         break;
        !           229:       ASSERT_ALWAYS (bufsize+1 <= sizeof (got));
        !           230:
        !           231:       got[bufsize] = '!';
        !           232:       ret = gmp_vsnprintf (got, bufsize, fmt, ap);
        !           233:
        !           234:       got_len = MIN (MAX(1,bufsize)-1, want_len);
        !           235:
        !           236:       if (got[bufsize] != '!')
        !           237:         {
        !           238:           printf ("gmp_vsnprintf overwrote bufsize sentinel\n");
        !           239:           goto error;
        !           240:         }
        !           241:
        !           242:       if (ret != want_len)
        !           243:         {
        !           244:           printf ("gmp_vsnprintf return value wrong\n");
        !           245:           goto error;
        !           246:         }
        !           247:
        !           248:       if (bufsize > 0)
        !           249:         {
        !           250:           if (memcmp (got, want, got_len) != 0 || got[got_len] != '\0')
        !           251:             {
        !           252:               printf ("gmp_vsnprintf wrong result string\n");
        !           253:             error:
        !           254:               printf ("  fmt       |%s|\n", fmt);
        !           255:               printf ("  bufsize   %u\n", bufsize);
        !           256:               printf ("  got       |%s|\n", got);
        !           257:               printf ("  want      |%.*s|\n", got_len, want);
        !           258:               printf ("  want full |%s|\n", want);
        !           259:               printf ("  ret       %d\n", ret);
        !           260:               printf ("  want_len  %d\n", want_len);
        !           261:               abort ();
        !           262:             }
        !           263:         }
        !           264:     }
        !           265: }
        !           266:
        !           267: void
        !           268: check_vasprintf (const char *want, const char *fmt, va_list ap)
        !           269: {
        !           270:   char  *got;
        !           271:   int   got_len, want_len;
        !           272:
        !           273:   want_len = strlen (want);
        !           274:   got_len = gmp_vasprintf (&got, fmt, ap);
        !           275:
        !           276:   if (got_len != want_len || strcmp (got, want) != 0)
        !           277:     {
        !           278:       printf ("gmp_vasprintf wrong\n");
        !           279:       printf ("  fmt      |%s|\n", fmt);
        !           280:       printf ("  got      |%s|\n", got);
        !           281:       printf ("  want     |%s|\n", want);
        !           282:       printf ("  got_len  %d\n", got_len);
        !           283:       printf ("  want_len %d\n", want_len);
        !           284:       abort ();
        !           285:     }
        !           286:   (*__gmp_free_func) (got, strlen(got)+1);
        !           287: }
        !           288:
        !           289: void
        !           290: check_obstack_vprintf (const char *want, const char *fmt, va_list ap)
        !           291: {
        !           292: #if HAVE_OBSTACK_VPRINTF
        !           293:   struct obstack  ob;
        !           294:   int   got_len, want_len, ob_len;
        !           295:   char  *got;
        !           296:
        !           297:   want_len = strlen (want);
        !           298:
        !           299:   obstack_init (&ob);
        !           300:   got_len = gmp_obstack_vprintf (&ob, fmt, ap);
        !           301:   got = obstack_base (&ob);
        !           302:   ob_len = obstack_object_size (&ob);
        !           303:
        !           304:   if (got_len != want_len
        !           305:       || ob_len != want_len
        !           306:       || memcmp (got, want, want_len) != 0)
        !           307:     {
        !           308:       printf ("gmp_obstack_vprintf wrong\n");
        !           309:       printf ("  fmt      |%s|\n", fmt);
        !           310:       printf ("  got      |%s|\n", got);
        !           311:       printf ("  want     |%s|\n", want);
        !           312:       printf ("  got_len  %d\n", got_len);
        !           313:       printf ("  ob_len   %d\n", ob_len);
        !           314:       printf ("  want_len %d\n", want_len);
        !           315:       abort ();
        !           316:     }
        !           317:   obstack_free (&ob, NULL);
        !           318: #endif
        !           319: }
        !           320:
        !           321:
        !           322: void
        !           323: #if HAVE_STDARG
        !           324: check_one (const char *want, const char *fmt, ...)
        !           325: #else
        !           326: check_one (va_alist)
        !           327:      va_dcl
        !           328: #endif
        !           329: {
        !           330:   va_list ap;
        !           331: #if HAVE_STDARG
        !           332:   va_start (ap, fmt);
        !           333: #else
        !           334:   const char  *want;
        !           335:   const char  *fmt;
        !           336:   va_start (ap);
        !           337:   want = va_arg (ap, const char *);
        !           338:   fmt = va_arg (ap, const char *);
        !           339: #endif
        !           340:
        !           341:   /* simplest first */
        !           342:   check_vsprintf (want, fmt, ap);
        !           343:   check_vfprintf (want, fmt, ap);
        !           344:   check_vsnprintf (want, fmt, ap);
        !           345:   check_vasprintf (want, fmt, ap);
        !           346:   check_obstack_vprintf (want, fmt, ap);
        !           347: }
        !           348:
        !           349:
        !           350: #define hex_or_octal_p(fmt)             \
        !           351:   (strchr (fmt, 'x') != NULL            \
        !           352:    || strchr (fmt, 'X') != NULL         \
        !           353:    || strchr (fmt, 'o') != NULL)
        !           354:
        !           355: void
        !           356: check_z (void)
        !           357: {
        !           358:   static const struct {
        !           359:     const char  *fmt;
        !           360:     const char  *z;
        !           361:     const char  *want;
        !           362:   } data[] = {
        !           363:     { "%Zd", "0",    "0" },
        !           364:     { "%Zd", "1",    "1" },
        !           365:     { "%Zd", "123",  "123" },
        !           366:     { "%Zd", "-1",   "-1" },
        !           367:     { "%Zd", "-123", "-123" },
        !           368:
        !           369:     { "%+Zd", "0",      "+0" },
        !           370:     { "%+Zd", "123",  "+123" },
        !           371:     { "%+Zd", "-123", "-123" },
        !           372:
        !           373:     { "%Zx",  "123",   "7b" },
        !           374:     { "%ZX",  "123",   "7B" },
        !           375:     { "%Zx", "-123",  "-7b" },
        !           376:     { "%ZX", "-123",  "-7B" },
        !           377:     { "%Zo",  "123",  "173" },
        !           378:     { "%Zo", "-123", "-173" },
        !           379:
        !           380:     { "%#Zx",    "0",     "0" },
        !           381:     { "%#ZX",    "0",     "0" },
        !           382:     { "%#Zx",  "123",  "0x7b" },
        !           383:     { "%#ZX",  "123",  "0X7B" },
        !           384:     { "%#Zx", "-123", "-0x7b" },
        !           385:     { "%#ZX", "-123", "-0X7B" },
        !           386:
        !           387:     { "%#Zo",    "0",     "0" },
        !           388:     { "%#Zo",  "123",  "0173" },
        !           389:     { "%#Zo", "-123", "-0173" },
        !           390:
        !           391:     { "%10Zd",      "0", "         0" },
        !           392:     { "%10Zd",    "123", "       123" },
        !           393:     { "%10Zd",   "-123", "      -123" },
        !           394:
        !           395:     { "%-10Zd",     "0", "0         " },
        !           396:     { "%-10Zd",   "123", "123       " },
        !           397:     { "%-10Zd",  "-123", "-123      " },
        !           398:
        !           399:     { "%+10Zd",   "123", "      +123" },
        !           400:     { "%+-10Zd",  "123", "+123      " },
        !           401:     { "%+10Zd",  "-123", "      -123" },
        !           402:     { "%+-10Zd", "-123", "-123      " },
        !           403:
        !           404:     { "%08Zd",    "0", "00000000" },
        !           405:     { "%08Zd",  "123", "00000123" },
        !           406:     { "%08Zd", "-123", "-0000123" },
        !           407:
        !           408:     { "%+08Zd",    "0", "+0000000" },
        !           409:     { "%+08Zd",  "123", "+0000123" },
        !           410:     { "%+08Zd", "-123", "-0000123" },
        !           411:
        !           412:     { "%#08Zx",    "0", "00000000" },
        !           413:     { "%#08Zx",  "123", "0x00007b" },
        !           414:     { "%#08Zx", "-123", "-0x0007b" },
        !           415:
        !           416:     { "%+#08Zx",    "0", "+0000000" },
        !           417:     { "%+#08Zx",  "123", "+0x0007b" },
        !           418:     { "%+#08Zx", "-123", "-0x0007b" },
        !           419:
        !           420:     { "%.0Zd", "0", "" },
        !           421:     { "%.1Zd", "0", "0" },
        !           422:     { "%.2Zd", "0", "00" },
        !           423:     { "%.3Zd", "0", "000" },
        !           424:   };
        !           425:
        !           426:   int        i, j, zeros;
        !           427:   mpz_t      z;
        !           428:   char       *nfmt;
        !           429:   mp_size_t  nsize;
        !           430:
        !           431:   mpz_init (z);
        !           432:
        !           433:   for (i = 0; i < numberof (data); i++)
        !           434:     {
        !           435:       mpz_set_str_or_abort (z, data[i].z, 0);
        !           436:
        !           437:       /* don't try negatives or forced sign in hex or octal */
        !           438:       if (mpz_fits_slong_p (z)
        !           439:           && ! (hex_or_octal_p (data[i].fmt)
        !           440:                 && (strchr (data[i].fmt, '+') != NULL || mpz_sgn(z) < 0)))
        !           441:         {
        !           442:           check_plain (data[i].want, data[i].fmt, mpz_get_si (z));
        !           443:         }
        !           444:
        !           445:       check_one (data[i].want, data[i].fmt, z);
        !           446:
        !           447:       /* Same again, with %N and possibly some high zero limbs */
        !           448:       nfmt = __gmp_allocate_strdup (data[i].fmt);
        !           449:       for (j = 0; nfmt[j] != '\0'; j++)
        !           450:         if (nfmt[j] == 'Z')
        !           451:           nfmt[j] = 'N';
        !           452:       for (zeros = 0; zeros <= 3; zeros++)
        !           453:         {
        !           454:           nsize = ABSIZ(z)+zeros;
        !           455:           MPZ_REALLOC (z, nsize);
        !           456:           nsize = (SIZ(z) >= 0 ? nsize : -nsize);
        !           457:           refmpn_zero (PTR(z)+ABSIZ(z), zeros);
        !           458:           check_one (data[i].want, nfmt, PTR(z), nsize);
        !           459:         }
        !           460:       __gmp_free_func (nfmt, strlen(nfmt)+1);
        !           461:     }
        !           462:
        !           463:   mpz_clear (z);
        !           464: }
        !           465:
        !           466: void
        !           467: check_q (void)
        !           468: {
        !           469:   static const struct {
        !           470:     const char  *fmt;
        !           471:     const char  *q;
        !           472:     const char  *want;
        !           473:   } data[] = {
        !           474:     { "%Qd",    "0",    "0" },
        !           475:     { "%Qd",    "1",    "1" },
        !           476:     { "%Qd",  "123",  "123" },
        !           477:     { "%Qd",   "-1",   "-1" },
        !           478:     { "%Qd", "-123", "-123" },
        !           479:     { "%Qd",  "3/2",  "3/2" },
        !           480:     { "%Qd", "-3/2", "-3/2" },
        !           481:
        !           482:     { "%+Qd", "0",      "+0" },
        !           483:     { "%+Qd", "123",  "+123" },
        !           484:     { "%+Qd", "-123", "-123" },
        !           485:     { "%+Qd", "5/8",  "+5/8" },
        !           486:     { "%+Qd", "-5/8", "-5/8" },
        !           487:
        !           488:     { "%Qx",  "123",   "7b" },
        !           489:     { "%QX",  "123",   "7B" },
        !           490:     { "%Qx",  "15/16", "f/10" },
        !           491:     { "%QX",  "15/16", "F/10" },
        !           492:     { "%Qx", "-123",  "-7b" },
        !           493:     { "%QX", "-123",  "-7B" },
        !           494:     { "%Qx", "-15/16", "-f/10" },
        !           495:     { "%QX", "-15/16", "-F/10" },
        !           496:     { "%Qo",  "123",  "173" },
        !           497:     { "%Qo", "-123", "-173" },
        !           498:     { "%Qo",  "16/17",  "20/21" },
        !           499:     { "%Qo", "-16/17", "-20/21" },
        !           500:
        !           501:     { "%#Qx",    "0",     "0" },
        !           502:     { "%#QX",    "0",     "0" },
        !           503:     { "%#Qx",  "123",  "0x7b" },
        !           504:     { "%#QX",  "123",  "0X7B" },
        !           505:     { "%#Qx",  "5/8",  "0x5/0x8" },
        !           506:     { "%#QX",  "5/8",  "0X5/0X8" },
        !           507:     { "%#Qx", "-123", "-0x7b" },
        !           508:     { "%#QX", "-123", "-0X7B" },
        !           509:     { "%#Qx", "-5/8", "-0x5/0x8" },
        !           510:     { "%#QX", "-5/8", "-0X5/0X8" },
        !           511:     { "%#Qo",    "0",     "0" },
        !           512:     { "%#Qo",  "123",  "0173" },
        !           513:     { "%#Qo", "-123", "-0173" },
        !           514:     { "%#Qo",  "5/7",  "05/07" },
        !           515:     { "%#Qo", "-5/7", "-05/07" },
        !           516:
        !           517:     /* zero denominator and showbase */
        !           518:     { "%#10Qo", "0/0",     "       0/0" },
        !           519:     { "%#10Qd", "0/0",     "       0/0" },
        !           520:     { "%#10Qx", "0/0",     "       0/0" },
        !           521:     { "%#10Qo", "123/0",   "    0173/0" },
        !           522:     { "%#10Qd", "123/0",   "     123/0" },
        !           523:     { "%#10Qx", "123/0",   "    0x7b/0" },
        !           524:     { "%#10QX", "123/0",   "    0X7B/0" },
        !           525:     { "%#10Qo", "-123/0",  "   -0173/0" },
        !           526:     { "%#10Qd", "-123/0",  "    -123/0" },
        !           527:     { "%#10Qx", "-123/0",  "   -0x7b/0" },
        !           528:     { "%#10QX", "-123/0",  "   -0X7B/0" },
        !           529:
        !           530:     { "%10Qd",      "0", "         0" },
        !           531:     { "%-10Qd",     "0", "0         " },
        !           532:     { "%10Qd",    "123", "       123" },
        !           533:     { "%-10Qd",   "123", "123       " },
        !           534:     { "%10Qd",   "-123", "      -123" },
        !           535:     { "%-10Qd",  "-123", "-123      " },
        !           536:
        !           537:     { "%+10Qd",   "123", "      +123" },
        !           538:     { "%+-10Qd",  "123", "+123      " },
        !           539:     { "%+10Qd",  "-123", "      -123" },
        !           540:     { "%+-10Qd", "-123", "-123      " },
        !           541:
        !           542:     { "%08Qd",    "0", "00000000" },
        !           543:     { "%08Qd",  "123", "00000123" },
        !           544:     { "%08Qd", "-123", "-0000123" },
        !           545:
        !           546:     { "%+08Qd",    "0", "+0000000" },
        !           547:     { "%+08Qd",  "123", "+0000123" },
        !           548:     { "%+08Qd", "-123", "-0000123" },
        !           549:
        !           550:     { "%#08Qx",    "0", "00000000" },
        !           551:     { "%#08Qx",  "123", "0x00007b" },
        !           552:     { "%#08Qx", "-123", "-0x0007b" },
        !           553:
        !           554:     { "%+#08Qx",    "0", "+0000000" },
        !           555:     { "%+#08Qx",  "123", "+0x0007b" },
        !           556:     { "%+#08Qx", "-123", "-0x0007b" },
        !           557:   };
        !           558:
        !           559:   int    i;
        !           560:   mpq_t  q;
        !           561:
        !           562:   mpq_init (q);
        !           563:
        !           564:   for (i = 0; i < numberof (data); i++)
        !           565:     {
        !           566:       mpq_set_str_or_abort (q, data[i].q, 0);
        !           567:       check_one (data[i].want, data[i].fmt, q);
        !           568:     }
        !           569:
        !           570:   mpq_clear (q);
        !           571: }
        !           572:
        !           573: void
        !           574: check_f (void)
        !           575: {
        !           576:   static const struct {
        !           577:     const char  *fmt;
        !           578:     const char  *f;
        !           579:     const char  *want;
        !           580:
        !           581:   } data[] = {
        !           582:
        !           583:     { "%Ff",    "0",    "0.000000" },
        !           584:     { "%Ff",  "123",  "123.000000" },
        !           585:     { "%Ff", "-123", "-123.000000" },
        !           586:
        !           587:     { "%+Ff",    "0",   "+0.000000" },
        !           588:     { "%+Ff",  "123", "+123.000000" },
        !           589:     { "%+Ff", "-123", "-123.000000" },
        !           590:
        !           591:     { "%.0Ff",    "0",    "0" },
        !           592:     { "%.0Ff",  "123",  "123" },
        !           593:     { "%.0Ff", "-123", "-123" },
        !           594:
        !           595:     { "%8.0Ff",    "0", "       0" },
        !           596:     { "%8.0Ff",  "123", "     123" },
        !           597:     { "%8.0Ff", "-123", "    -123" },
        !           598:
        !           599:     { "%08.0Ff",    "0", "00000000" },
        !           600:     { "%08.0Ff",  "123", "00000123" },
        !           601:     { "%08.0Ff", "-123", "-0000123" },
        !           602:
        !           603:     { "%10.2Ff",       "0", "      0.00" },
        !           604:     { "%10.2Ff",    "0.25", "      0.25" },
        !           605:     { "%10.2Ff",  "123.25", "    123.25" },
        !           606:     { "%10.2Ff", "-123.25", "   -123.25" },
        !           607:
        !           608:     { "%-10.2Ff",       "0", "0.00      " },
        !           609:     { "%-10.2Ff",    "0.25", "0.25      " },
        !           610:     { "%-10.2Ff",  "123.25", "123.25    " },
        !           611:     { "%-10.2Ff", "-123.25", "-123.25   " },
        !           612:
        !           613:     { "%.2Ff", "0.00000000000001", "0.00" },
        !           614:     { "%.2Ff", "0.002",            "0.00" },
        !           615:     { "%.2Ff", "0.008",            "0.01" },
        !           616:
        !           617:     { "%.0Ff", "123.00000000000001", "123" },
        !           618:     { "%.0Ff", "123.2",              "123" },
        !           619:     { "%.0Ff", "123.8",              "124" },
        !           620:
        !           621:     { "%.0Ff",  "999999.9", "1000000" },
        !           622:     { "%.0Ff", "3999999.9", "4000000" },
        !           623:
        !           624:     { "%Fe",    "0",  "0.000000e+00" },
        !           625:     { "%Fe",    "1",  "1.000000e+00" },
        !           626:     { "%Fe",  "123",  "1.230000e+02" },
        !           627:
        !           628:     { "%FE",    "0",  "0.000000E+00" },
        !           629:     { "%FE",    "1",  "1.000000E+00" },
        !           630:     { "%FE",  "123",  "1.230000E+02" },
        !           631:
        !           632:     { "%Fe",    "0",  "0.000000e+00" },
        !           633:     { "%Fe",    "1",  "1.000000e+00" },
        !           634:
        !           635:     { "%.0Fe",     "10000000000",    "1e+10" },
        !           636:     { "%.0Fe",    "-10000000000",   "-1e+10" },
        !           637:
        !           638:     { "%.2Fe",     "10000000000",  "1.00e+10" },
        !           639:     { "%.2Fe",    "-10000000000", "-1.00e+10" },
        !           640:
        !           641:     { "%8.0Fe",    "10000000000", "   1e+10" },
        !           642:     { "%8.0Fe",   "-10000000000", "  -1e+10" },
        !           643:
        !           644:     { "%-8.0Fe",   "10000000000", "1e+10   " },
        !           645:     { "%-8.0Fe",  "-10000000000", "-1e+10  " },
        !           646:
        !           647:     { "%12.2Fe",   "10000000000", "    1.00e+10" },
        !           648:     { "%12.2Fe",  "-10000000000", "   -1.00e+10" },
        !           649:
        !           650:     { "%012.2Fe",  "10000000000", "00001.00e+10" },
        !           651:     { "%012.2Fe", "-10000000000", "-0001.00e+10" },
        !           652:
        !           653:     { "%Fg",   "0", "0" },
        !           654:     { "%Fg",   "1", "1" },
        !           655:     { "%Fg",   "-1", "-1" },
        !           656:
        !           657:     { "%.0Fg", "0", "0" },
        !           658:     { "%.0Fg", "1", "1" },
        !           659:     { "%.0Fg", "-1", "-1" },
        !           660:
        !           661:     { "%.1Fg", "100", "1e+02" },
        !           662:     { "%.2Fg", "100", "1e+02" },
        !           663:     { "%.3Fg", "100", "100" },
        !           664:     { "%.4Fg", "100", "100" },
        !           665:
        !           666:     { "%Fg", "0.001",    "0.001" },
        !           667:     { "%Fg", "0.0001",   "0.0001" },
        !           668:     { "%Fg", "0.00001",  "1e-05" },
        !           669:     { "%Fg", "0.000001", "1e-06" },
        !           670:
        !           671:     { "%.4Fg", "1.00000000000001", "1" },
        !           672:     { "%.4Fg", "100000000000001",  "1e+14" },
        !           673:
        !           674:     { "%.4Fg", "12345678", "1.235e+07" },
        !           675:
        !           676:     { "%Fa", "0","0x0p+0" },
        !           677:     { "%FA", "0","0X0P+0" },
        !           678:
        !           679:     { "%Fa", "1","0x1p+0" },
        !           680:     { "%Fa", "65535","0xf.fffp+12" },
        !           681:     { "%Fa", "65536","0x1p+16" },
        !           682:     { "%F.10a", "65536","0x1.0000000000p+16" },
        !           683:     { "%F.1a", "65535","0x1.0p+16" },
        !           684:     { "%F.0a", "65535","0x1p+16" },
        !           685:
        !           686:     { "%.2Ff", "0.99609375", "1.00" },
        !           687:     { "%.Ff",  "0.99609375", "0.99609375" },
        !           688:     { "%.Fe",  "0.99609375", "9.9609375e-01" },
        !           689:     { "%.Fg",  "0.99609375", "0.99609375" },
        !           690:     { "%.20Fg",  "1000000", "1000000" },
        !           691:     { "%.Fg",  "1000000", "1000000" },
        !           692:
        !           693:     { "%#.0Ff", "1", "1." },
        !           694:     { "%#.0Fe", "1", "1.e+00" },
        !           695:     { "%#.0Fg", "1", "1." },
        !           696:
        !           697:     { "%#.1Ff", "1", "1.0" },
        !           698:     { "%#.1Fe", "1", "1.0e+00" },
        !           699:     { "%#.1Fg", "1", "1." },
        !           700:
        !           701:     { "%#.4Ff", "1234", "1234.0000" },
        !           702:     { "%#.4Fe", "1234", "1.2340e+03" },
        !           703:     { "%#.4Fg", "1234", "1234." },
        !           704:
        !           705:     { "%#.8Ff", "1234", "1234.00000000" },
        !           706:     { "%#.8Fe", "1234", "1.23400000e+03" },
        !           707:     { "%#.8Fg", "1234", "1234.0000" },
        !           708:
        !           709:   };
        !           710:
        !           711:   int     i;
        !           712:   mpf_t   f;
        !           713:   double  d;
        !           714:
        !           715:   mpf_init2 (f, 256L);
        !           716:
        !           717:   for (i = 0; i < numberof (data); i++)
        !           718:     {
        !           719:       if (data[i].f[0] == '0' && data[i].f[1] == 'x')
        !           720:         mpf_set_str_or_abort (f, data[i].f, 16);
        !           721:       else
        !           722:         mpf_set_str_or_abort (f, data[i].f, 10);
        !           723:
        !           724:       /* if mpf->double doesn't truncate, then expect same result */
        !           725:       d = mpf_get_d (f);
        !           726:       if (mpf_cmp_d (f, d) == 0)
        !           727:         check_plain (data[i].want, data[i].fmt, d);
        !           728:
        !           729:       check_one (data[i].want, data[i].fmt, f);
        !           730:     }
        !           731:
        !           732:   mpf_clear (f);
        !           733: }
        !           734:
        !           735:
        !           736: void
        !           737: check_n (void)
        !           738: {
        !           739:   {
        !           740:     int  n = -1;
        !           741:     check_one ("blah", "%nblah", &n);
        !           742:     ASSERT_ALWAYS (n == 0);
        !           743:   }
        !           744:
        !           745:   {
        !           746:     int  n = -1;
        !           747:     check_one ("hello ", "hello %n", &n);
        !           748:     ASSERT_ALWAYS (n == 6);
        !           749:   }
        !           750:
        !           751:   {
        !           752:     int  n = -1;
        !           753:     check_one ("hello  world", "hello %n world", &n);
        !           754:     ASSERT_ALWAYS (n == 6);
        !           755:   }
        !           756:
        !           757: #define CHECK_N(type, string)                           \
        !           758:   do {                                                  \
        !           759:     type  x[2];                                         \
        !           760:     char  fmt[128];                                     \
        !           761:                                                         \
        !           762:     x[0] = ~ (type) 0;                                  \
        !           763:     x[1] = ~ (type) 0;                                  \
        !           764:     sprintf (fmt, "%%d%%%sn%%d", string);               \
        !           765:     check_one ("123456", fmt, 123, &x[0], 456);         \
        !           766:                                                         \
        !           767:     /* should write whole of x[0] and none of x[1] */   \
        !           768:     ASSERT_ALWAYS (x[0] == 3);                          \
        !           769:     ASSERT_ALWAYS (x[1] == (type) ~ (type) 0);         \
        !           770:                                                         \
        !           771:   } while (0)
        !           772:
        !           773:   CHECK_N (char,      "hh");
        !           774:   CHECK_N (long,      "l");
        !           775: #if HAVE_LONG_LONG
        !           776:   CHECK_N (long long, "L");
        !           777: #endif
        !           778: #if HAVE_INTMAX_T
        !           779:   CHECK_N (intmax_t,  "j");
        !           780: #endif
        !           781: #if HAVE_PTRDIFF_T
        !           782:   CHECK_N (ptrdiff_t, "t");
        !           783: #endif
        !           784:   CHECK_N (short,     "h");
        !           785:   CHECK_N (size_t,    "z");
        !           786:
        !           787:   {
        !           788:     mpz_t  x[2];
        !           789:     mpz_init_set_si (x[0], -987L);
        !           790:     mpz_init_set_si (x[1],  654L);
        !           791:     check_one ("123456", "%d%Zn%d", 123, x[0], 456);
        !           792:     MPZ_CHECK_FORMAT (x[0]);
        !           793:     MPZ_CHECK_FORMAT (x[1]);
        !           794:     ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
        !           795:     ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
        !           796:     mpz_clear (x[0]);
        !           797:     mpz_clear (x[1]);
        !           798:   }
        !           799:
        !           800:   {
        !           801:     mpq_t  x[2];
        !           802:     mpq_init (x[0]);
        !           803:     mpq_init (x[1]);
        !           804:     mpq_set_ui (x[0], -987L, 654L);
        !           805:     mpq_set_ui (x[1], 4115L, 226L);
        !           806:     check_one ("123456", "%d%Qn%d", 123, x[0], 456);
        !           807:     MPQ_CHECK_FORMAT (x[0]);
        !           808:     MPQ_CHECK_FORMAT (x[1]);
        !           809:     ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
        !           810:     ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
        !           811:     mpq_clear (x[0]);
        !           812:     mpq_clear (x[1]);
        !           813:   }
        !           814:
        !           815:   {
        !           816:     mpf_t  x[2];
        !           817:     mpf_init (x[0]);
        !           818:     mpf_init (x[1]);
        !           819:     mpf_set_ui (x[0], -987L);
        !           820:     mpf_set_ui (x[1],  654L);
        !           821:     check_one ("123456", "%d%Fn%d", 123, x[0], 456);
        !           822:     MPF_CHECK_FORMAT (x[0]);
        !           823:     MPF_CHECK_FORMAT (x[1]);
        !           824:     ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
        !           825:     ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
        !           826:     mpf_clear (x[0]);
        !           827:     mpf_clear (x[1]);
        !           828:   }
        !           829:
        !           830:   {
        !           831:     mp_limb_t  a[5];
        !           832:     mp_limb_t  a_want[numberof(a)];
        !           833:     mp_size_t  i;
        !           834:
        !           835:     a[0] = 123;
        !           836:     check_one ("blah", "bl%Nnah", a, (mp_size_t) 0);
        !           837:     ASSERT_ALWAYS (a[0] == 123);
        !           838:
        !           839:     MPN_ZERO (a_want, numberof (a_want));
        !           840:     for (i = 1; i < numberof (a); i++)
        !           841:       {
        !           842:         check_one ("blah", "bl%Nnah", a, i);
        !           843:         a_want[0] = 2;
        !           844:         ASSERT_ALWAYS (mpn_cmp (a, a_want, i) == 0);
        !           845:       }
        !           846:   }
        !           847: }
        !           848:
        !           849:
        !           850: void
        !           851: check_misc (void)
        !           852: {
        !           853:   mpz_t  z;
        !           854:   mpf_t  f;
        !           855:
        !           856:   mpz_init (z);
        !           857:   mpf_init2 (f, 128L);
        !           858:
        !           859:   check_one ("!", "%c", '!');
        !           860:
        !           861:   check_one ("hello world", "hello %s", "world");
        !           862:   check_one ("hello:", "%s:", "hello");
        !           863:   mpz_set_ui (z, 0L);
        !           864:   check_one ("hello0", "%s%Zd", "hello", z, z);
        !           865:
        !           866:   {
        !           867:     static char  xs[801];
        !           868:     memset (xs, 'x', sizeof(xs)-1);
        !           869:     check_one (xs, "%s", xs);
        !           870:   }
        !           871:
        !           872:   mpz_set_ui (z, 12345L);
        !           873:   check_one ("     12345", "%*Zd", 10, z);
        !           874:   check_one ("0000012345", "%0*Zd", 10, z);
        !           875:   check_one ("12345     ", "%*Zd", -10, z);
        !           876:   check_one ("12345 and 678", "%Zd and %d", z, 678);
        !           877:   check_one ("12345,1,12345,2,12345", "%Zd,%d,%Zd,%d,%Zd", z, 1, z, 2, z);
        !           878:
        !           879:   /* from the glibc info docs */
        !           880:   mpz_set_si (z, 0L);
        !           881:   check_one ("|    0|0    |   +0|+0   |    0|00000|     |   00|0|",
        !           882:              "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
        !           883:              /**/ z,    z,    z,     z,    z,    z,     z,     z,  z);
        !           884:   mpz_set_si (z, 1L);
        !           885:   check_one ("|    1|1    |   +1|+1   |    1|00001|    1|   01|1|",
        !           886:              "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
        !           887:              /**/ z,    z,    z,     z,    z,    z,     z,     z,  z);
        !           888:   mpz_set_si (z, -1L);
        !           889:   check_one ("|   -1|-1   |   -1|-1   |   -1|-0001|   -1|  -01|-1|",
        !           890:              "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
        !           891:              /**/ z,    z,    z,     z,    z,    z,     z,     z,  z);
        !           892:   mpz_set_si (z, 100000L);
        !           893:   check_one ("|100000|100000|+100000|+100000| 100000|100000|100000|100000|100000|",
        !           894:              "|%5Zd|%-5Zd|%+5Zd|%+-5Zd|% 5Zd|%05Zd|%5.0Zd|%5.2Zd|%Zd|",
        !           895:              /**/ z,    z,    z,     z,    z,    z,     z,     z,  z);
        !           896:   mpz_set_si (z, 0L);
        !           897:   check_one ("|    0|    0|    0|    0|    0|    0|  00000000|",
        !           898:              "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
        !           899:              /**/ z,   z,   z,    z,    z,    z,       z);
        !           900:   mpz_set_si (z, 1L);
        !           901:   check_one ("|    1|    1|    1|   01|  0x1|  0X1|0x00000001|",
        !           902:              "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
        !           903:              /**/ z,   z,   z,    z,    z,    z,       z);
        !           904:   mpz_set_si (z, 100000L);
        !           905:   check_one ("|303240|186a0|186A0|0303240|0x186a0|0X186A0|0x000186a0|",
        !           906:              "|%5Zo|%5Zx|%5ZX|%#5Zo|%#5Zx|%#5ZX|%#10.8Zx|",
        !           907:              /**/ z,   z,   z,    z,    z,    z,       z);
        !           908:
        !           909:   /* %zd for size_t won't be available on old systems, and running something
        !           910:      to see if it works might be bad, so only try it on glibc, and only on a
        !           911:      new enough version (glibc 2.0 doesn't have %zd) */
        !           912: #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
        !           913:   mpz_set_ui (z, 789L);
        !           914:   check_one ("456 789 blah", "%zd %Zd blah", (size_t) 456, z);
        !           915: #endif
        !           916:
        !           917:   mpz_clear (z);
        !           918:   mpf_clear (f);
        !           919: }
        !           920:
        !           921:
        !           922: int
        !           923: main (int argc, char *argv[])
        !           924: {
        !           925:   if (argc > 1 && strcmp (argv[1], "-s") == 0)
        !           926:     option_check_printf = 1;
        !           927:
        !           928:   tests_start ();
        !           929:   check_vfprintf_fp = fopen (CHECK_VFPRINTF_FILENAME, "w+");
        !           930:   ASSERT_ALWAYS (check_vfprintf_fp != NULL);
        !           931:
        !           932:   check_z ();
        !           933:   check_q ();
        !           934:   check_f ();
        !           935:   check_n ();
        !           936:   check_misc ();
        !           937:
        !           938:   ASSERT_ALWAYS (fclose (check_vfprintf_fp) == 0);
        !           939:   unlink (CHECK_VFPRINTF_FILENAME);
        !           940:   tests_end ();
        !           941:   exit (0);
        !           942: }

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