From f4308c51cc73a8b1397c436f8dd667e15d6d0b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Nieper-Wi=C3=9Fkirchen?= Date: Wed, 20 May 2020 13:59:31 +0200 Subject: [PATCH] New module to accurately print (long) doubles in C locale. --- ChangeLog | 18 +++++++++++++ MODULES.html.sh | 2 ++ lib/c-dtoastr.c | 3 +++ lib/c-ldtoastr.c | 3 +++ lib/ftoastr.c | 23 +++++++++++----- lib/ftoastr.h | 6 +++++ modules/c-dtoastr | 27 +++++++++++++++++++ modules/c-dtoastr-tests | 18 +++++++++++++ modules/c-ldtoastr | 27 +++++++++++++++++++ modules/c-ldtoastr-tests | 18 +++++++++++++ tests/test-c-dtoastr.c | 58 ++++++++++++++++++++++++++++++++++++++++ tests/test-c-dtoastr.sh | 15 +++++++++++ tests/test-c-ldtoastr.c | 58 ++++++++++++++++++++++++++++++++++++++++ tests/test-c-ldtoastr.sh | 15 +++++++++++ 14 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 lib/c-dtoastr.c create mode 100644 lib/c-ldtoastr.c create mode 100644 modules/c-dtoastr create mode 100644 modules/c-dtoastr-tests create mode 100644 modules/c-ldtoastr create mode 100644 modules/c-ldtoastr-tests create mode 100644 tests/test-c-dtoastr.c create mode 100644 tests/test-c-dtoastr.sh create mode 100644 tests/test-c-ldtoastr.c create mode 100644 tests/test-c-ldtoastr.sh diff --git a/ChangeLog b/ChangeLog index 1c39b92e6..becb40eec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2020-05-20 Marc Nieper-Wißkirchen + + c-dtoastr: new module + c-ldtoastr: new module + These modules provide the same functionality as the modules + dtoastr and ldtoastr except for the formatting taking place in the + C locale. + * MODULES.html.sh: Add c-dtoastr and c-ldtoastr. + * lib/c-dtoastr.c, lib/c-ldtoastr.c: New files + * lib/ftoastr.c: Prefix exported functions when the macro C_LOCALE is + defined. Use c_snprintf and c_strtod/c_strtold instead of + snprintf and strtod/strtold whhen the macro C_LOCALE is defined. + * lib/ftoastr.h: Add prototypes for c_dtoastr and c_ldtoastr. + * modules/c-dtoastr, modules/c-dtoastr-tests, modules/c-ldtoastr, + modules/c-ldtoastr-tests: New files. + * tests/test-c-dtoastr.c, tests/test-c-dtoastr.sh, + tests-c-ldtoastr.c tests-c-ldtoastr.sh: New files. + 2020-05-19 Paul Eggert ftoastr: fix ifndef typo diff --git a/MODULES.html.sh b/MODULES.html.sh index 318a15a1d..280bd14da 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2319,6 +2319,8 @@ func_all_modules () func_echo "$element" func_begin_table + func_module c-dtoastr + func_module c-ldtoast func_module dtoastr func_module ftoastr func_module intprops diff --git a/lib/c-dtoastr.c b/lib/c-dtoastr.c new file mode 100644 index 000000000..b57524fb1 --- /dev/null +++ b/lib/c-dtoastr.c @@ -0,0 +1,3 @@ +#define LENGTH 2 +#define C_LOCALE 1 +#include "ftoastr.c" diff --git a/lib/c-ldtoastr.c b/lib/c-ldtoastr.c new file mode 100644 index 000000000..5446fc3e7 --- /dev/null +++ b/lib/c-ldtoastr.c @@ -0,0 +1,3 @@ +#define LENGTH 3 +#define C_LOCALE 1 +#include "ftoastr.c" diff --git a/lib/ftoastr.c b/lib/ftoastr.c index 7a7d4113c..47a83152e 100644 --- a/lib/ftoastr.c +++ b/lib/ftoastr.c @@ -33,20 +33,28 @@ #include #include +#ifdef C_LOCALE +# include "c-snprintf.h" +# include "c-strtod.h" +# define PREFIX(name) c_ ## name +#else +# define PREFIX(name) name +#endif + #if LENGTH == 3 # define FLOAT long double # define FLOAT_DIG LDBL_DIG # define FLOAT_MIN LDBL_MIN # define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND -# define FTOASTR ldtoastr +# define FTOASTR PREFIX (ldtoastr) # define PROMOTED_FLOAT long double -# define STRTOF strtold +# define STRTOF PREFIX (strtold) #elif LENGTH == 2 # define FLOAT double # define FLOAT_DIG DBL_DIG # define FLOAT_MIN DBL_MIN # define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND -# define FTOASTR dtoastr +# define FTOASTR PREFIX (dtoastr) # define PROMOTED_FLOAT double #else # define LENGTH 1 @@ -54,7 +62,7 @@ # define FLOAT_DIG FLT_DIG # define FLOAT_MIN FLT_MIN # define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND -# define FTOASTR ftoastr +# define FTOASTR PREFIX (ftoastr) # define PROMOTED_FLOAT double # if HAVE_STRTOF # define STRTOF strtof @@ -65,13 +73,16 @@ may generate one or two extra digits, but that's better than not working at all. */ #ifndef STRTOF -# define STRTOF strtod +# define STRTOF PREFIX (strtod) #endif /* On hosts where it's not known that snprintf works, use sprintf to implement the subset needed here. Typically BUFSIZE is big enough and there's little or no performance hit. */ -#if ! GNULIB_SNPRINTF +#ifdef C_LOCALE +# undef snprintf +# define snprintf c_snprintf +#elif ! GNULIB_SNPRINTF # undef snprintf # define snprintf ftoastr_snprintf static int diff --git a/lib/ftoastr.h b/lib/ftoastr.h index 852e4000d..78b569f3d 100644 --- a/lib/ftoastr.h +++ b/lib/ftoastr.h @@ -49,6 +49,12 @@ int ftoastr (char *buf, size_t bufsize, int flags, int width, float x); int dtoastr (char *buf, size_t bufsize, int flags, int width, double x); int ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); +/* The last two functions except that the formatting takes place in + the C locale. */ +int c_dtoastr (char *buf, size_t bufsize, int flags, int width, double x); +int c_ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); + + /* Flag values for ftoastr etc. These can be ORed together. */ enum { diff --git a/modules/c-dtoastr b/modules/c-dtoastr new file mode 100644 index 000000000..fd0054ade --- /dev/null +++ b/modules/c-dtoastr @@ -0,0 +1,27 @@ +Description: +Convert double to accurate string in C locale. + +Files: +lib/ftoastr.h +lib/ftoastr.c +lib/c-dtoastr.c + +Depends-on: +extensions +intprops +c-snprintf +c-strtod + +configure.ac: + +Makefile.am: +lib_SOURCES += c-dtoastr.c + +Include: +"ftoastr.h" + +License: +GPL + +Maintainer: +Marc Nieper-Wisskirchen \ No newline at end of file diff --git a/modules/c-dtoastr-tests b/modules/c-dtoastr-tests new file mode 100644 index 000000000..687d7669b --- /dev/null +++ b/modules/c-dtoastr-tests @@ -0,0 +1,18 @@ +Files: +tests/test-c-dtoastr.c +tests/test-c-dtoastr.sh +m4/locale-fr.m4 +tests/macros.h + +Depends-on: +setlocale +snprintf + +configure.ac: +gt_LOCALE_FR + +Makefile.am: +TESTS += test-c-dtoastr.sh +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' +check_PROGRAMS += test-c-dtoastr +test_c_dtoastr_LDADD = $(LDADD) $(LIB_SETLOCALE) diff --git a/modules/c-ldtoastr b/modules/c-ldtoastr new file mode 100644 index 000000000..ce1e9dbf7 --- /dev/null +++ b/modules/c-ldtoastr @@ -0,0 +1,27 @@ +Description: +Convert long double to accurate string in C locale. + +Files: +lib/ftoastr.h +lib/ftoastr.c +lib/c-ldtoastr.c + +Depends-on: +extensions +intprops +c-snprintf +c-strtold + +configure.ac: + +Makefile.am: +lib_SOURCES += c-ldtoastr.c + +Include: +"ftoastr.h" + +License: +GPL + +Maintainer: +Marc Nieper-Wisskirchen \ No newline at end of file diff --git a/modules/c-ldtoastr-tests b/modules/c-ldtoastr-tests new file mode 100644 index 000000000..2d4c7f81e --- /dev/null +++ b/modules/c-ldtoastr-tests @@ -0,0 +1,18 @@ +Files: +tests/test-c-ldtoastr.c +tests/test-c-ldtoastr.sh +m4/locale-fr.m4 +tests/macros.h + +Depends-on: +setlocale +snprintf + +configure.ac: +gt_LOCALE_FR + +Makefile.am: +TESTS += test-c-ldtoastr.sh +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' +check_PROGRAMS += test-c-ldtoastr +test_c_ldtoastr_LDADD = $(LDADD) $(LIB_SETLOCALE) diff --git a/tests/test-c-dtoastr.c b/tests/test-c-dtoastr.c new file mode 100644 index 000000000..373e7c4bc --- /dev/null +++ b/tests/test-c-dtoastr.c @@ -0,0 +1,58 @@ +/* Test of c_dtoastr() function. + Copyright (C) 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "ftoastr.h" + +#include +#include +#include + +#include "macros.h" + +int +main (int argc, char *argv[]) +{ + /* configure should already have checked that the locale is supported. */ + if (setlocale (LC_ALL, "") == NULL) + return 1; + + /* Test behaviour of snprintf() as a "control group". + (We should be running in a locale where ',' is the decimal point.) */ + { + char s[16]; + + snprintf (s, sizeof s, "%#.0f", 1.0); + if (!strcmp (s, "1.")) + { + /* Skip the test, since we're not in a useful locale for testing. */ + return 77; + } + ASSERT (!strcmp (s, "1,")); + } + + /* Test behaviour of c_dtoastr(). + It should always use '.' as the decimal point. */ + { + char buf[DBL_BUFSIZE_BOUND]; + + c_dtoastr (buf, sizeof buf, 0, 0, 0.1); + ASSERT (!strcmp (buf, "0.1")); + } + + return 0; +} diff --git a/tests/test-c-dtoastr.sh b/tests/test-c-dtoastr.sh new file mode 100644 index 000000000..ef0e459b4 --- /dev/null +++ b/tests/test-c-dtoastr.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Test in an ISO-8859-1 or ISO-8859-15 locale. +: ${LOCALE_FR=fr_FR} +if test $LOCALE_FR = none; then + if test -f /usr/bin/localedef; then + echo "Skipping test: no traditional french locale is installed" + else + echo "Skipping test: no traditional french locale is supported" + fi + exit 77 +fi + +LC_ALL=$LOCALE_FR \ +${CHECKER} ./test-c-dtoastr${EXEEXT} 1 diff --git a/tests/test-c-ldtoastr.c b/tests/test-c-ldtoastr.c new file mode 100644 index 000000000..140f0c6d8 --- /dev/null +++ b/tests/test-c-ldtoastr.c @@ -0,0 +1,58 @@ +/* Test of c_ldtoastr() function. + Copyright (C) 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "ftoastr.h" + +#include +#include +#include + +#include "macros.h" + +int +main (int argc, char *argv[]) +{ + /* configure should already have checked that the locale is supported. */ + if (setlocale (LC_ALL, "") == NULL) + return 1; + + /* Test behaviour of snprintf() as a "control group". + (We should be running in a locale where ',' is the decimal point.) */ + { + char s[16]; + + snprintf (s, sizeof s, "%#.0f", 1.0); + if (!strcmp (s, "1.")) + { + /* Skip the test, since we're not in a useful locale for testing. */ + return 77; + } + ASSERT (!strcmp (s, "1,")); + } + + /* Test behaviour of c_ldtoastr(). + It should always use '.' as the decimal point. */ + { + char buf[DBL_BUFSIZE_BOUND]; + + c_ldtoastr (buf, sizeof buf, 0, 0, 0.1); + ASSERT (!strcmp (buf, "0.1")); + } + + return 0; +} diff --git a/tests/test-c-ldtoastr.sh b/tests/test-c-ldtoastr.sh new file mode 100644 index 000000000..ad7a32a14 --- /dev/null +++ b/tests/test-c-ldtoastr.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Test in an ISO-8859-1 or ISO-8859-15 locale. +: ${LOCALE_FR=fr_FR} +if test $LOCALE_FR = none; then + if test -f /usr/bin/localedef; then + echo "Skipping test: no traditional french locale is installed" + else + echo "Skipping test: no traditional french locale is supported" + fi + exit 77 +fi + +LC_ALL=$LOCALE_FR \ +${CHECKER} ./test-c-ldtoastr${EXEEXT} 1 -- 2.20.1