* 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.
2017-09-23 Bruno Haible <bruno@clisp.org>
+ 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.
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
+@item
+This function uses a wrong locale for the numbers on some platforms:
+glibc 2.23.
@end itemize
Portability problems not fixed by Gnulib:
--- /dev/null
+/* 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <monetary.h>
+
+#include <locale.h>
+#include <stdarg.h>
+
+#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
+ <https://sourceware.org/bugzilla/show_bug.cgi?id=19633>. */
+ 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;
+}
--- /dev/null
+# 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 <monetary.h> to declare strfmon_l().
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ dnl On Mac OS X 10.12, <monetary.h> may declare strfmon_l() if
+ dnl _USE_EXTENDED_LOCALES_ is defined. But this symbol is supposed
+ dnl to be defined by <xlocale.h>, not by us.
+
+ AC_CHECK_FUNCS_ONCE([strfmon_l])
+ if test $ac_cv_func_strfmon_l = yes; then
+ dnl Test for bug <https://sourceware.org/bugzilla/show_bug.cgi?id=19633>
+ 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 <features.h>
+#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], [
+ :
+])
--- /dev/null
+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
+<monetary.h>
+#endif
+
+License:
+LGPLv2+
+
+Maintainer:
+all
--- /dev/null
+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
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if HAVE_MONETARY_H
+# include <monetary.h>
+#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 <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <https://sourceware.org/bugzilla/show_bug.cgi?id=19633>. */
+ 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;
+}