Add missing strfmon_l. Noticed by Bruno Haible. Add test case.

This commit is contained in:
joerg 2017-08-16 13:53:19 +00:00
parent 25f03d5f57
commit 29f5b623d9
7 changed files with 154 additions and 34 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.223 2017/08/11 20:47:58 ryo Exp $
# $NetBSD: mi,v 1.224 2017/08/16 13:53:19 joerg Exp $
./etc/mtree/set.debug comp-sys-root
./usr/lib comp-sys-usr compatdir
./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile
@ -1954,6 +1954,7 @@
./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbstowcs.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbtowc.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_sprintf.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_strfmon.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_toupper.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcscoll.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcscspn.debug tests-lib-debug debug,atf,compattestfile

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.760 2017/08/10 04:31:58 ryo Exp $
# $NetBSD: mi,v 1.761 2017/08/16 13:53:20 joerg Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -2551,6 +2551,7 @@
./usr/tests/lib/libc/locale/t_mbstowcs tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_mbtowc tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_sprintf tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_strfmon tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_toupper tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_wcscoll tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/locale/t_wcscspn tests-lib-tests compattestfile,atf

View File

@ -1,4 +1,4 @@
/* $NetBSD: monetary.h,v 1.2 2008/09/21 16:59:46 christos Exp $ */
/* $NetBSD: monetary.h,v 1.3 2017/08/16 13:53:20 joerg Exp $ */
/*-
* Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
@ -44,6 +44,16 @@ typedef _BSD_SSIZE_T_ ssize_t;
#undef _BSD_SSIZE_T_
#endif
#if defined(_NETBSD_SOURCE)
# ifndef __LOCALE_T_DECLARED
typedef struct _locale *locale_t;
# define __LOCALE_T_DECLARED
# endif
__BEGIN_DECLS
ssize_t strfmon_l(char * __restrict, size_t, locale_t, const char * __restrict, ...)
__attribute__((__format__(__strfmon__, 4, 5)));
#endif
__BEGIN_DECLS
ssize_t strfmon(char * __restrict, size_t, const char * __restrict, ...)
__attribute__((__format__(__strfmon__, 3, 4)));

View File

@ -1,4 +1,4 @@
.\" $NetBSD: strfmon.3,v 1.5 2014/03/18 18:20:37 riastradh Exp $
.\" $NetBSD: strfmon.3,v 1.6 2017/08/16 13:53:20 joerg Exp $
.\"
.\" Copyright (c) 2001 Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org>
.\" All rights reserved.
@ -26,7 +26,7 @@
.\"
.\" From: FreeBSD: Id: strfmon.3,v 1.7 2003/01/06 06:21:25 tjr Exp
.\"
.Dd October 12, 2002
.Dd August 15, 2017
.Dt STRFMON 3
.Os
.Sh NAME
@ -38,6 +38,8 @@
.In monetary.h
.Ft ssize_t
.Fn strfmon "char * restrict s" "size_t maxsize" "const char * restrict format" "..."
.Ft ssize_t
.Fn strfmon_l "char * restrict s" "size_t maxsize" "locale_t loc" "const char * restrict format" "..."
.Sh DESCRIPTION
The
.Fn strfmon
@ -49,6 +51,14 @@ No more than
.Fa maxsize
bytes are placed into the array.
.Pp
The
.Fn strfmon_l
function behaves the same as
.fn strfmon ,
but uses the locale
.Fa loc
instead of the process global locale.
.Pp
The format string is composed of zero or more directives:
ordinary characters (not
.Cm % ) ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: strfmon.c,v 1.10 2012/03/21 14:19:15 christos Exp $ */
/* $NetBSD: strfmon.c,v 1.11 2017/08/16 13:53:20 joerg Exp $ */
/*-
* Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
@ -32,14 +32,11 @@
#if 0
__FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.14 2003/03/20 08:18:55 ache Exp $");
#else
__RCSID("$NetBSD: strfmon.c,v 1.10 2012/03/21 14:19:15 christos Exp $");
__RCSID("$NetBSD: strfmon.c,v 1.11 2017/08/16 13:53:20 joerg Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#if defined(__NetBSD__)
#include "namespace.h"
#include <monetary.h>
#endif
#include <sys/types.h>
#include <assert.h>
@ -47,11 +44,14 @@ __RCSID("$NetBSD: strfmon.c,v 1.10 2012/03/21 14:19:15 christos Exp $");
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <monetary.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "setlocale_local.h"
/* internal flags */
#define NEED_GROUPING 0x01 /* print digits grouped (default) */
@ -104,15 +104,14 @@ __RCSID("$NetBSD: strfmon.c,v 1.10 2012/03/21 14:19:15 christos Exp $");
groups++; \
} while (/* CONSTCOND */ 0)
static void __setup_vars(int, char *, char *, char *, const char **);
static int __calc_left_pad(int, char *);
static char *__format_grouped_double(double, int *, int, int, int);
static void __setup_vars(struct lconv *, int, char *, char *, char *, const char **);
static int __calc_left_pad(struct lconv *, int, char *);
static char *__format_grouped_double(struct lconv *, double, int *, int, int, int);
ssize_t
strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
...)
static ssize_t
vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
const char * __restrict format, va_list ap)
{
va_list ap;
char *dst; /* output destination pointer */
const char *fmt; /* current format poistion pointer */
struct lconv *lc; /* pointer to lconv structure */
@ -136,9 +135,7 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
char *tmpptr; /* temporary vars */
int sverrno;
va_start(ap, format);
lc = localeconv();
lc = localeconv_l(loc);
dst = s;
fmt = format;
asciivalue = NULL;
@ -263,21 +260,21 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
/* fill left_prec with amount of padding chars */
if (left_prec >= 0) {
pad_size = __calc_left_pad((flags ^ IS_NEGATIVE),
pad_size = __calc_left_pad(lc, (flags ^ IS_NEGATIVE),
currency_symbol) -
__calc_left_pad(flags, currency_symbol);
__calc_left_pad(lc, flags, currency_symbol);
if (pad_size < 0)
pad_size = 0;
}
asciivalue = __format_grouped_double(value, &flags,
asciivalue = __format_grouped_double(lc, value, &flags,
left_prec, right_prec, pad_char);
if (asciivalue == NULL)
goto end_error; /* errno already set */
/* to ENOMEM by malloc() */
/* set some variables for later use */
__setup_vars(flags, &cs_precedes, &sep_by_space,
__setup_vars(lc, flags, &cs_precedes, &sep_by_space,
&sign_posn, &signstr);
/*
@ -392,7 +389,6 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
}
PRINT('\0');
va_end(ap);
free(asciivalue);
free(currency_symbol);
return (dst - s - 1); /* return size of put data except trailing '\0' */
@ -411,14 +407,12 @@ end_error:
if (currency_symbol != NULL)
free(currency_symbol);
errno = sverrno;
va_end(ap);
return (-1);
}
static void
__setup_vars(int flags, char *cs_precedes, char *sep_by_space,
__setup_vars(struct lconv *lc, int flags, char *cs_precedes, char *sep_by_space,
char *sign_posn, const char **signstr) {
struct lconv *lc = localeconv();
if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) {
*cs_precedes = lc->int_n_cs_precedes;
@ -454,13 +448,13 @@ __setup_vars(int flags, char *cs_precedes, char *sep_by_space,
}
static int
__calc_left_pad(int flags, char *cur_symb) {
__calc_left_pad(struct lconv *lc, int flags, char *cur_symb) {
char cs_precedes, sep_by_space, sign_posn;
const char *signstr;
size_t left_chars = 0;
__setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);
__setup_vars(lc, flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);
if (cs_precedes != 0) {
left_chars += strlen(cur_symb);
@ -506,7 +500,7 @@ get_groups(int size, char *grouping) {
/* convert double to ASCII */
static char *
__format_grouped_double(double value, int *flags,
__format_grouped_double(struct lconv *lc, double value, int *flags,
int left_prec, int right_prec, int pad_char) {
char *rslt;
@ -518,7 +512,6 @@ __format_grouped_double(double value, int *flags,
int padded;
struct lconv *lc = localeconv();
char *grouping;
char decimal_point;
char thousands_sep;
@ -627,3 +620,31 @@ __format_grouped_double(double value, int *flags,
free(avalue);
return (rslt);
}
ssize_t
strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
...)
{
ssize_t rv;
va_list ap;
va_start(ap, format);
rv = vstrfmon_l(s, maxsize, _current_locale(), format, ap);
va_end(ap);
return rv;
}
ssize_t
strfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
const char * __restrict format, ...)
{
ssize_t rv;
va_list ap;
va_start(ap, format);
rv = vstrfmon_l(s, maxsize, loc, format, ap);
va_end(ap);
return rv;
}

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.11 2017/07/23 18:51:21 perseant Exp $
# $NetBSD: Makefile,v 1.12 2017/08/16 13:53:20 joerg Exp $
.include <bsd.own.mk>
@ -21,6 +21,7 @@ TESTS_C+= t_wctype
TESTS_C+= t_btowc
TESTS_C+= t_wcscoll
TESTS_C+= t_ducet
TESTS_C+= t_strfmon
COPTS.t_wctomb.c += -Wno-stack-protector
COPTS.t_digittoint.c += -Wno-unused-variable

View File

@ -0,0 +1,76 @@
/* $NetBSD: t_strfmon.c,v 1.1 2017/08/16 13:53:20 joerg Exp $ */
/*-
* Copyright (c) 2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Joerg Sonnenberger.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_strfmon.c,v 1.1 2017/08/16 13:53:20 joerg Exp $");
#include <atf-c.h>
#include <locale.h>
#include <monetary.h>
ATF_TC(strfmon);
ATF_TC_HEAD(strfmon, tc)
{
atf_tc_set_md_var(tc, "descr",
"Checks strfmon_l under diferent locales");
}
ATF_TC_BODY(strfmon, tc)
{
const struct {
const char *locale;
const char *expected;
} tests[] = {
{ "C", "[**1234.57] [**1234.57]" },
{ "de_DE.UTF-8", "[ **1234,57 €] [ **1.234,57 EUR ]" },
{ "en_GB.UTF-8", "[ £**1234.57] [ GBP **1,234.57]" },
};
locale_t loc;
size_t i;
char buf[80];
for (i = 0; i < __arraycount(tests); ++i) {
loc = newlocale(LC_MONETARY_MASK, tests[i].locale, 0);
ATF_REQUIRE(loc != 0);
strfmon_l(buf, sizeof(buf), loc, "[%^=*#6n] [%=*#6i]",
1234.567, 1234.567);
ATF_REQUIRE_STREQ(tests[i].expected, buf);
freelocale(loc);
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, strfmon);
return atf_no_error();
}