From 61419a00613066a02ee1dee8649e12dcc2f62466 Mon Sep 17 00:00:00 2001 From: vlefevre Date: Mon, 30 Jul 2018 13:43:03 +0000 Subject: [acinclude.m4,configure.ac] Check the support of the group flag for native integers, which is a Single UNIX Specification extension. [src/vasprintf.c] Fixed bug with the P length modifier (mpfr_prec_t). [tests/tsprintf.c] Added testcases. (merged changesets r12958-12959,12961-12964 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@12967 280ebfd0-de03-0410-8827-d642c229c3f4 --- acinclude.m4 | 25 +++++++++++++++++++++++++ configure.ac | 3 ++- src/vasprintf.c | 20 +++++++++++--------- tests/tsprintf.c | 20 ++++++++++++++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 1c17223ae..88ed99c62 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1433,6 +1433,31 @@ MPFR_FUNC_GMP_PRINTF_SPEC([td], [ptrdiff_t], [ [AC_DEFINE([NPRINTF_T], 1, [gmp_printf cannot read ptrdiff_t])]) ]) +dnl MPFR_CHECK_PRINTF_GROUPFLAG +dnl --------------------------- +dnl Check the support of the group flag for native integers, which is +dnl a Single UNIX Specification extension. +dnl This will be used to enable some tests, as the implementation of +dnl the P length modifier for mpfr_*printf relies on this support. + +AC_DEFUN([MPFR_CHECK_PRINTF_GROUPFLAG], [ +AC_MSG_CHECKING(if gmp_printf supports the ' group flag) +AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +]], [[ + char s[256]; + + if (gmp_sprintf (s, "%'d", 17) == -1) return 1; + return (strcmp (s, "17") != 0); +]])], + [AC_MSG_RESULT(yes) + AC_DEFINE([PRINTF_GROUPFLAG], 1, [Define if gmp_printf supports the ' group flag])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(cannot test, assume no)]) +]) +]) + dnl MPFR_LTO dnl -------- dnl To be representative, we need: diff --git a/configure.ac b/configure.ac index bea5aed06..80a183544 100644 --- a/configure.ac +++ b/configure.ac @@ -708,7 +708,8 @@ if test -z "$enable_mini_gmp" ; then [AC_MSG_RESULT(yes) MPFR_CHECK_GMP MPFR_CHECK_DBL2INT_BUG - MPFR_CHECK_PRINTF_SPEC], + MPFR_CHECK_PRINTF_SPEC + MPFR_CHECK_PRINTF_GROUPFLAG], [AC_MSG_RESULT(no) AC_MSG_WARN([==========================================================]) AC_MSG_WARN(['gmp.h' and 'libgmp' seem to have different versions or]) diff --git a/src/vasprintf.c b/src/vasprintf.c index 99c8780b7..09df8c942 100644 --- a/src/vasprintf.c +++ b/src/vasprintf.c @@ -259,6 +259,8 @@ specinfo_is_valid (struct printf_spec spec) } } +/* Note: additional flags should be added to the MPFR_PREC_ARG code + for gmp_asprintf (when supported). */ static const char * parse_flags (const char *format, struct printf_spec *specinfo) { @@ -2220,7 +2222,7 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt, /* output mpfr_prec_t variable */ { char *s; - char format[MPFR_PREC_FORMAT_SIZE + 6]; /* see examples below */ + char format[MPFR_PREC_FORMAT_SIZE + 12]; /* e.g. "%0#+ -'*.*ld\0" */ size_t length; mpfr_prec_t prec; @@ -2232,14 +2234,14 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt, start = fmt; /* construct format string, like "%*.*hd" "%*.*d" or "%*.*ld" */ - format[0] = '%'; - format[1] = '*'; - format[2] = '.'; - format[3] = '*'; - format[4] = '\0'; - strcat (format, MPFR_PREC_FORMAT_TYPE); - format[4 + MPFR_PREC_FORMAT_SIZE] = spec.spec; - format[5 + MPFR_PREC_FORMAT_SIZE] = '\0'; + sprintf (format, "%%%s%s%s%s%s%s*.*" MPFR_PREC_FORMAT_TYPE "%c", + spec.pad == '0' ? "0" : "", + spec.alt ? "#" : "", + spec.showsign ? "+" : "", + spec.space ? " " : "", + spec.left ? "-" : "", + spec.group ? "'" : "", + spec.spec); length = gmp_asprintf (&s, format, spec.width, spec.prec, prec); MPFR_ASSERTN (length >= 0); /* guaranteed by GMP 6 */ buffer_cat (&buf, s, length); diff --git a/tests/tsprintf.c b/tests/tsprintf.c index 21f298ec2..cf220c25c 100644 --- a/tests/tsprintf.c +++ b/tests/tsprintf.c @@ -232,6 +232,22 @@ decimal (void) /* specifier 'P' for precision */ check_vsprintf ("128", "%Pu", p); check_vsprintf ("00128", "%.5Pu", p); + check_vsprintf (" 128", "%5Pu", p); + check_vsprintf ("000128", "%06Pu", p); + check_vsprintf ("128 :", "%-7Pu:", p); + check_vsprintf ("000128:", "%-2.6Pd:", p); + check_vsprintf (" 000128:", "%8.6Pd:", p); + check_vsprintf ("000128 :", "%-8.6Pd:", p); + check_vsprintf ("+128:", "%+d:", p); + check_vsprintf (" 128:", "% d:", p); + check_vsprintf ("80:", "% x:", p); + check_vsprintf ("0x80:", "% #x:", p); + check_vsprintf ("0x80:", "%0#+ -x:", p); + check_vsprintf ("0200:", "%0#+ -o:", p); + check_vsprintf ("+0000128 :", "%0+ *.*Pd:", -9, 7, p); + check_vsprintf ("+12345 :", "%0+ -*.*Pd:", -9, -3, (mpfr_prec_t) 12345); + /* Do not add a test like "%05.1Pd" as MS Windows is buggy: when + a precision is given, the '0' flag must be ignored. */ /* special numbers */ mpfr_set_inf (x, 1); @@ -1545,6 +1561,10 @@ test_locale (void) check_sprintf ("00000001,000", "%'012.4Rg", x); check_sprintf ("000000001,000", "%'013.4Rg", x); +#ifdef PRINTF_GROUPFLAG + check_vsprintf ("+01,234,567 :", "%0+ -'13.10Pd:", (mpfr_prec_t) 1234567); +#endif + mpfr_clear (x); } -- cgit v1.2.1