>From 19882ec15628386c45977ade98293e26791b7a15 Mon Sep 17 00:00:00 2001
From: Bruno Haible
Date: Sat, 23 Sep 2017 12:22:17 +0200
Subject: [PATCH 3/3] strfmon_l: New module.
* modules/strfmon_l: New file.
* lib/strfmon_l.c: New file.
* m4/strfmon_l.m4: New file.
* doc/posix-functions/strfmon_l.texi: Mention the new module.
* modules/strfmon_l-tests: New file.
* tests/test-strfmon_l.c: New file.
---
ChangeLog | 8 ++++
doc/posix-functions/strfmon_l.texi | 5 +-
lib/strfmon_l.c | 64 ++++++++++++++++++++++++++
m4/strfmon_l.m4 | 46 +++++++++++++++++++
modules/strfmon_l | 31 +++++++++++++
modules/strfmon_l-tests | 12 +++++
tests/test-strfmon_l.c | 93 ++++++++++++++++++++++++++++++++++++++
7 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 lib/strfmon_l.c
create mode 100644 m4/strfmon_l.m4
create mode 100644 modules/strfmon_l
create mode 100644 modules/strfmon_l-tests
create mode 100644 tests/test-strfmon_l.c
diff --git a/ChangeLog b/ChangeLog
index 2b88ede..a317d01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2017-09-23 Bruno Haible
+ strfmon_l: New module.
+ * modules/strfmon_l: New file.
+ * lib/strfmon_l.c: New file.
+ * m4/strfmon_l.m4: New file.
+ * doc/posix-functions/strfmon_l.texi: Mention the new module.
+ * modules/strfmon_l-tests: New file.
+ * tests/test-strfmon_l.c: New file.
+
monetary: New module.
* modules/monetary: New file.
* lib/monetary.in.h: New file.
diff --git a/doc/posix-functions/strfmon_l.texi b/doc/posix-functions/strfmon_l.texi
index b9da883..754dd1d 100644
--- a/doc/posix-functions/strfmon_l.texi
+++ b/doc/posix-functions/strfmon_l.texi
@@ -4,10 +4,13 @@
POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/strfmon_l.html}
-Gnulib module: ---
+Gnulib module: strfmon_l
Portability problems fixed by Gnulib:
@itemize
address@hidden
+This function uses a wrong locale for the numbers on some platforms:
+glibc 2.23.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/strfmon_l.c b/lib/strfmon_l.c
new file mode 100644
index 0000000..ac80d65
--- /dev/null
+++ b/lib/strfmon_l.c
@@ -0,0 +1,64 @@
+/* strfmon_l override.
+ Copyright (C) 2017 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, 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
+
+/* Specification. */
+#include
+
+#include
+#include
+
+#undef strfmon_l
+
+/* This override can only support a limited number of arguments. */
+#define MAX_ARG_WORDS 16
+
+ssize_t
+rpl_strfmon_l (char *s, size_t maxsize, locale_t locale, const char *format, ...)
+{
+ /* Work around glibc 2.23 bug
+ . */
+ va_list argptr;
+ double args[MAX_ARG_WORDS];
+ int i;
+ locale_t orig_locale;
+ ssize_t result;
+
+ orig_locale = uselocale ((locale_t)0);
+
+ if (uselocale (locale) == (locale_t)0)
+ /* errno is set. */
+ return -1;
+
+ va_start (argptr, format);
+ /* Hack: Consume more arguments than those that are actually given. */
+ for (i = 0; i < MAX_ARG_WORDS; i++)
+ args[i] = va_arg (argptr, double);
+
+ result = strfmon_l (s, maxsize, locale, format,
+ args[0], args[1], args[2], args[3], args[4], args[5],
+ args[6], args[7], args[8], args[9], args[10], args[11],
+ args[12], args[13], args[14], args[15]);
+
+ va_end (argptr);
+
+ if (uselocale (orig_locale) == (locale_t)0)
+ /* errno is set. */
+ return -1;
+
+ return result;
+}
diff --git a/m4/strfmon_l.m4 b/m4/strfmon_l.m4
new file mode 100644
index 0000000..d6dd48a
--- /dev/null
+++ b/m4/strfmon_l.m4
@@ -0,0 +1,46 @@
+# strfmon_l.m4 serial 1
+dnl Copyright (C) 2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRFMON_L],
+[
+ AC_REQUIRE([gl_MONETARY_H_DEFAULTS])
+
+ dnl Persuade glibc to declare strfmon_l().
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ dnl On Mac OS X 10.12, may declare strfmon_l() if
+ dnl _USE_EXTENDED_LOCALES_ is defined. But this symbol is supposed
+ dnl to be defined by , not by us.
+
+ AC_CHECK_FUNCS_ONCE([strfmon_l])
+ if test $ac_cv_func_strfmon_l = yes; then
+ dnl Test for bug
+ dnl which was fixed in glibc-2.24.
+ AC_CACHE_CHECK([whether strfmon_l works],
+ [gl_cv_strfmon_l_works],
+ [AC_EGREP_CPP([Unlucky],
+ [
+#include
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)
+ Unlucky GNU user
+ #endif
+#endif
+ ],
+ [gl_cv_strfmon_l_works=no],
+ [gl_cv_strfmon_l_works="guessing yes"])
+ ])
+ if test "$gl_cv_strfmon_l_works" = no; then
+ REPLACE_STRFMON_L=1
+ fi
+ else
+ HAVE_STRFMON_L=0
+ fi
+])
+
+# Prerequisites of lib/strfmon_l.c.
+AC_DEFUN([gl_PREREQ_STRFMON_L], [
+ :
+])
diff --git a/modules/strfmon_l b/modules/strfmon_l
new file mode 100644
index 0000000..42a4c96
--- /dev/null
+++ b/modules/strfmon_l
@@ -0,0 +1,31 @@
+Description:
+strfmon_l() function: formatted conversion of monetary value to string.
+
+Files:
+lib/strfmon_l.c
+m4/strfmon_l.m4
+
+Depends-on:
+monetary
+extensions
+
+configure.ac:
+gl_FUNC_STRFMON_L
+if test $REPLACE_STRFMON_L = 1; then
+ AC_LIBOBJ([strfmon_l])
+ gl_PREREQ_STRFMON_L
+fi
+gl_MONETARY_MODULE_INDICATOR([strfmon_l])
+
+Makefile.am:
+
+Include:
+#if HAVE_MONETARY_H
+
+#endif
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/strfmon_l-tests b/modules/strfmon_l-tests
new file mode 100644
index 0000000..871962c
--- /dev/null
+++ b/modules/strfmon_l-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-strfmon_l.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-strfmon_l
+check_PROGRAMS += test-strfmon_l
diff --git a/tests/test-strfmon_l.c b/tests/test-strfmon_l.c
new file mode 100644
index 0000000..4605c8d
--- /dev/null
+++ b/tests/test-strfmon_l.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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
+
+#if HAVE_MONETARY_H
+# include
+#endif
+
+#include "signature.h"
+#if HAVE_STRFMON_L
+SIGNATURE_CHECK (strfmon_l, ssize_t, (char *s, size_t maxsize, locale_t locale,
+ const char *format, ...));
+#endif
+
+#include
+#include
+#include
+
+#include "macros.h"
+
+int
+main (void)
+{
+#if HAVE_STRFMON_L
+ /* Simple test in the C locale. */
+ {
+ char buf[80];
+ locale_t loc;
+ ssize_t ret;
+
+ loc = newlocale (LC_ALL_MASK, "C", NULL);
+ ASSERT (loc != NULL);
+ ret = strfmon_l (buf, sizeof (buf), loc, "%^#5.0n", 123.4);
+ ASSERT ( (ret == 5 && strcmp (buf, " 123") == 0) /* AIX, Solaris */
+ || (ret == 6 && strcmp (buf, " 123") == 0) /* glibc */
+ || (ret == 7 && strcmp (buf, " 123 ") == 0) /* Mac OS X */
+ );
+ }
+
+ /* Test whether the decimal point comes from the right locale:
+ glibc bug . */
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
+ {
+ fprintf (stderr, "Skipping test: English Unicode locale is not installed\n");
+ return 77;
+ }
+ if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
+ {
+ fprintf (stderr, "Skipping test: English Unicode locale is not installed\n");
+ return 77;
+ }
+ {
+ char expected_buf[80];
+ locale_t loc;
+ char buf[80];
+
+ setlocale (LC_ALL, "en_US.UTF-8");
+ ASSERT (strfmon (expected_buf, sizeof (expected_buf), "%.2n", 123.5) >= 0);
+ setlocale (LC_ALL, "de_DE.UTF-8");
+ loc = newlocale (LC_ALL_MASK, "en_US.UTF-8", NULL);
+ ASSERT (strfmon_l (buf, sizeof (buf), loc, "%.2n", 123.5) >= 0);
+ ASSERT (strcmp (buf, expected_buf) == 0);
+ }
+ {
+ char expected_buf[80];
+ locale_t loc;
+ char buf[80];
+
+ setlocale (LC_ALL, "de_DE.UTF-8");
+ ASSERT (strfmon (expected_buf, sizeof (expected_buf), "%.2n", 123.5) >= 0);
+ setlocale (LC_ALL, "en_US.UTF-8");
+ loc = newlocale (LC_ALL_MASK, "de_DE.UTF-8", NULL);
+ ASSERT (strfmon_l (buf, sizeof (buf), loc, "%.2n", 123.5) >= 0);
+ ASSERT (strcmp (buf, expected_buf) == 0);
+ }
+#endif
+
+ return 0;
+}
--
2.7.4