Add missing strfmon_l. Noticed by Bruno Haible. Add test case.
This commit is contained in:
parent
25f03d5f57
commit
29f5b623d9
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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 % ) ,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue