📄 t-printf.c
字号:
/* Test gmp_printf and related functions.Copyright 2001, 2002 Free Software Foundation, Inc.This file is part of the GNU MP Library.The GNU MP Library is free software; you can redistribute it and/or modifyit under the terms of the GNU Lesser General Public License as published bythe Free Software Foundation; either version 2.1 of the License, or (at youroption) any later version.The GNU MP Library is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITYor FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General PublicLicense for more details.You should have received a copy of the GNU Lesser General Public Licensealong with the GNU MP Library; see the file COPYING.LIB. If not, write tothe Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,MA 02111-1307, USA. *//* Usage: t-printf [-s] -s Check the data against the system printf, where possible. This is only an option since we don't want to fail if the system printf is faulty or strange. */#include "config.h"#if HAVE_STDARG#include <stdarg.h>#else#include <varargs.h>#endif#include <stddef.h> /* for ptrdiff_t */#include <stdio.h>#include <stdlib.h>#include <string.h>#if HAVE_OBSTACK_VPRINTF#define obstack_chunk_alloc tests_allocate#define obstack_chunk_free tests_free_nosize#include <obstack.h>#endif#if HAVE_INTTYPES_H# include <inttypes.h> /* for intmax_t */#else# if HAVE_STDINT_H# include <stdint.h># endif#endif#if HAVE_UNISTD_H#include <unistd.h> /* for unlink */#endif#include "gmp.h"#include "gmp-impl.h"#include "tests.h"int option_check_printf = 0;#define CHECK_VFPRINTF_FILENAME "t-printf.tmp"FILE *check_vfprintf_fp;/* From any of the tests run here. */#define MAX_OUTPUT 1024void#if HAVE_STDARGcheck_plain (const char *want, const char *fmt_orig, ...)#elsecheck_plain (va_alist) va_dcl#endif{ char got[MAX_OUTPUT]; int got_len, want_len; size_t fmtsize; char *fmt, *q; const char *p; va_list ap;#if HAVE_STDARG va_start (ap, fmt_orig);#else const char *want; const char *fmt_orig; va_start (ap); want = va_arg (ap, const char *); fmt_orig = va_arg (ap, const char *);#endif if (! option_check_printf) return; fmtsize = strlen (fmt_orig) + 1; fmt = (*__gmp_allocate_func) (fmtsize); for (p = fmt_orig, q = fmt; *p != '\0'; p++) { switch (*p) { case 'a': case 'A': /* The exact value of the exponent isn't guaranteed in glibc, and it and gmp_printf do slightly different things, so don't compare directly. */ goto done; case 'F': if (p > fmt_orig && *(p-1) == '.') goto done; /* don't test the "all digits" cases */ /* discard 'F' type */ break; case 'Z': /* transmute */ *q++ = 'l'; break; default: *q++ = *p; break; } } *q = '\0'; want_len = strlen (want); ASSERT_ALWAYS (want_len < sizeof(got)); got_len = vsprintf (got, fmt, ap); if (got_len != want_len || strcmp (got, want) != 0) { printf ("wanted data doesn't match plain vsprintf\n"); printf (" fmt |%s|\n", fmt); printf (" got |%s|\n", got); printf (" want |%s|\n", want); printf (" got_len %d\n", got_len); printf (" want_len %d\n", want_len); abort (); } done: (*__gmp_free_func) (fmt, fmtsize);}voidcheck_vsprintf (const char *want, const char *fmt, va_list ap){ char got[MAX_OUTPUT]; int got_len, want_len; want_len = strlen (want); got_len = gmp_vsprintf (got, fmt, ap); if (got_len != want_len || strcmp (got, want) != 0) { printf ("gmp_vsprintf wrong\n"); printf (" fmt |%s|\n", fmt); printf (" got |%s|\n", got); printf (" want |%s|\n", want); printf (" got_len %d\n", got_len); printf (" want_len %d\n", want_len); abort (); }}voidcheck_vfprintf (const char *want, const char *fmt, va_list ap){ char got[MAX_OUTPUT]; int got_len, want_len, fread_len; long ftell_len; want_len = strlen (want); rewind (check_vfprintf_fp); got_len = gmp_vfprintf (check_vfprintf_fp, fmt, ap); ASSERT_ALWAYS (got_len != -1); ASSERT_ALWAYS (fflush (check_vfprintf_fp) == 0); ftell_len = ftell (check_vfprintf_fp); ASSERT_ALWAYS (ftell_len != -1); rewind (check_vfprintf_fp); ASSERT_ALWAYS (ftell_len <= sizeof(got)); fread_len = fread (got, 1, ftell_len, check_vfprintf_fp); if (got_len != want_len || ftell_len != want_len || fread_len != want_len || memcmp (got, want, want_len) != 0) { printf ("gmp_vfprintf wrong\n"); printf (" fmt |%s|\n", fmt); printf (" got |%.*s|\n", fread_len, got); printf (" want |%s|\n", want); printf (" got_len %d\n", got_len); printf (" ftell_len %ld\n", ftell_len); printf (" fread_len %d\n", fread_len); printf (" want_len %d\n", want_len); abort (); }}voidcheck_vsnprintf (const char *want, const char *fmt, va_list ap){ char got[MAX_OUTPUT+1]; int ret, got_len, want_len; size_t bufsize; want_len = strlen (want); bufsize = -1; for (;;) { /* do 0 to 5, then want-5 to want+5 */ bufsize++; if (bufsize > 5 && bufsize < want_len-5) bufsize = want_len-5; if (bufsize > want_len + 5) break; ASSERT_ALWAYS (bufsize+1 <= sizeof (got)); got[bufsize] = '!'; ret = gmp_vsnprintf (got, bufsize, fmt, ap); got_len = MIN (MAX(1,bufsize)-1, want_len); if (got[bufsize] != '!') { printf ("gmp_vsnprintf overwrote bufsize sentinel\n"); goto error; } if (ret != want_len) { printf ("gmp_vsnprintf return value wrong\n"); goto error; } if (bufsize > 0) { if (memcmp (got, want, got_len) != 0 || got[got_len] != '\0') { printf ("gmp_vsnprintf wrong result string\n"); error: printf (" fmt |%s|\n", fmt); printf (" bufsize %u\n", bufsize); printf (" got |%s|\n", got); printf (" want |%.*s|\n", got_len, want); printf (" want full |%s|\n", want); printf (" ret %d\n", ret); printf (" want_len %d\n", want_len); abort (); } } }}voidcheck_vasprintf (const char *want, const char *fmt, va_list ap){ char *got; int got_len, want_len; want_len = strlen (want); got_len = gmp_vasprintf (&got, fmt, ap); if (got_len != want_len || strcmp (got, want) != 0) { printf ("gmp_vasprintf wrong\n"); printf (" fmt |%s|\n", fmt); printf (" got |%s|\n", got); printf (" want |%s|\n", want); printf (" got_len %d\n", got_len); printf (" want_len %d\n", want_len); abort (); } (*__gmp_free_func) (got, strlen(got)+1);}voidcheck_obstack_vprintf (const char *want, const char *fmt, va_list ap){#if HAVE_OBSTACK_VPRINTF struct obstack ob; int got_len, want_len, ob_len; char *got; want_len = strlen (want); obstack_init (&ob); got_len = gmp_obstack_vprintf (&ob, fmt, ap); got = obstack_base (&ob); ob_len = obstack_object_size (&ob); if (got_len != want_len || ob_len != want_len || memcmp (got, want, want_len) != 0) { printf ("gmp_obstack_vprintf wrong\n"); printf (" fmt |%s|\n", fmt); printf (" got |%s|\n", got); printf (" want |%s|\n", want); printf (" got_len %d\n", got_len); printf (" ob_len %d\n", ob_len); printf (" want_len %d\n", want_len); abort (); } obstack_free (&ob, NULL);#endif}void#if HAVE_STDARGcheck_one (const char *want, const char *fmt, ...)#elsecheck_one (va_alist) va_dcl#endif{ va_list ap;#if HAVE_STDARG va_start (ap, fmt);#else const char *want; const char *fmt; va_start (ap); want = va_arg (ap, const char *); fmt = va_arg (ap, const char *);#endif /* simplest first */ check_vsprintf (want, fmt, ap); check_vfprintf (want, fmt, ap); check_vsnprintf (want, fmt, ap); check_vasprintf (want, fmt, ap); check_obstack_vprintf (want, fmt, ap);}#define hex_or_octal_p(fmt) \ (strchr (fmt, 'x') != NULL \ || strchr (fmt, 'X') != NULL \ || strchr (fmt, 'o') != NULL)voidcheck_z (void){ static const struct { const char *fmt; const char *z; const char *want; } data[] = { { "%Zd", "0", "0" }, { "%Zd", "1", "1" }, { "%Zd", "123", "123" }, { "%Zd", "-1", "-1" }, { "%Zd", "-123", "-123" }, { "%+Zd", "0", "+0" }, { "%+Zd", "123", "+123" }, { "%+Zd", "-123", "-123" }, { "%Zx", "123", "7b" }, { "%ZX", "123", "7B" }, { "%Zx", "-123", "-7b" }, { "%ZX", "-123", "-7B" }, { "%Zo", "123", "173" }, { "%Zo", "-123", "-173" }, { "%#Zx", "0", "0" }, { "%#ZX", "0", "0" }, { "%#Zx", "123", "0x7b" }, { "%#ZX", "123", "0X7B" }, { "%#Zx", "-123", "-0x7b" }, { "%#ZX", "-123", "-0X7B" }, { "%#Zo", "0", "0" }, { "%#Zo", "123", "0173" }, { "%#Zo", "-123", "-0173" }, { "%10Zd", "0", " 0" }, { "%10Zd", "123", " 123" }, { "%10Zd", "-123", " -123" }, { "%-10Zd", "0", "0 " }, { "%-10Zd", "123", "123 " }, { "%-10Zd", "-123", "-123 " }, { "%+10Zd", "123", " +123" }, { "%+-10Zd", "123", "+123 " }, { "%+10Zd", "-123", " -123" }, { "%+-10Zd", "-123", "-123 " }, { "%08Zd", "0", "00000000" }, { "%08Zd", "123", "00000123" }, { "%08Zd", "-123", "-0000123" }, { "%+08Zd", "0", "+0000000" }, { "%+08Zd", "123", "+0000123" }, { "%+08Zd", "-123", "-0000123" }, { "%#08Zx", "0", "00000000" }, { "%#08Zx", "123", "0x00007b" }, { "%#08Zx", "-123", "-0x0007b" }, { "%+#08Zx", "0", "+0000000" }, { "%+#08Zx", "123", "+0x0007b" }, { "%+#08Zx", "-123", "-0x0007b" }, { "%.0Zd", "0", "" }, { "%.1Zd", "0", "0" }, { "%.2Zd", "0", "00" }, { "%.3Zd", "0", "000" }, }; int i, j, zeros; mpz_t z; char *nfmt; mp_size_t nsize; mpz_init (z); for (i = 0; i < numberof (data); i++) { mpz_set_str_or_abort (z, data[i].z, 0); /* don't try negatives or forced sign in hex or octal */ if (mpz_fits_slong_p (z) && ! (hex_or_octal_p (data[i].fmt) && (strchr (data[i].fmt, '+') != NULL || mpz_sgn(z) < 0))) { check_plain (data[i].want, data[i].fmt, mpz_get_si (z)); } check_one (data[i].want, data[i].fmt, z); /* Same again, with %N and possibly some high zero limbs */ nfmt = __gmp_allocate_strdup (data[i].fmt); for (j = 0; nfmt[j] != '\0'; j++) if (nfmt[j] == 'Z') nfmt[j] = 'N'; for (zeros = 0; zeros <= 3; zeros++) { nsize = ABSIZ(z)+zeros; MPZ_REALLOC (z, nsize); nsize = (SIZ(z) >= 0 ? nsize : -nsize); refmpn_zero (PTR(z)+ABSIZ(z), zeros); check_one (data[i].want, nfmt, PTR(z), nsize); } __gmp_free_func (nfmt, strlen(nfmt)+1); } mpz_clear (z);}voidcheck_q (void){ static const struct { const char *fmt; const char *q; const char *want;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -