[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

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>