--- strfmon.c.orig 2003-05-20 15:23:25.000000000 -0700 +++ strfmon.c 2005-02-27 11:52:19.000000000 -0800 @@ -28,6 +28,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.14 2003/03/20 08:18:55 ache Exp $"); +#include "xlocale_private.h" + #include <sys/types.h> #include <ctype.h> #include <errno.h> @@ -61,9 +63,9 @@ PRINT(*tmps++); \ } while (0) -#define GET_NUMBER(VAR) do { \ +#define GET_NUMBER(VAR,LOC) do { \ VAR = 0; \ - while (isdigit((unsigned char)*fmt)) { \ + while (isdigit_l((unsigned char)*fmt, (LOC))) { \ VAR *= 10; \ VAR += *fmt - '0'; \ fmt++; \ @@ -83,15 +85,14 @@ groups++; \ } while (0) -static void __setup_vars(int, char *, char *, char *, char **); -static int __calc_left_pad(int, char *); -static char *__format_grouped_double(double, int *, int, int, int); - -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) +static void __setup_vars(int, char *, char *, char *, char **, struct lconv *); +static int __calc_left_pad(int, char *, struct lconv *); +static char *__format_grouped_double(double, int *, int, int, int, struct lconv *, locale_t); + +static ssize_t +_strfmon(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 */ @@ -115,9 +116,7 @@ char *tmpptr; /* temporary vars */ int sverrno; - va_start(ap, format); - - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -181,8 +180,8 @@ } /* field Width */ - if (isdigit((unsigned char)*fmt)) { - GET_NUMBER(width); + if (isdigit_l((unsigned char)*fmt, loc)) { + GET_NUMBER(width, loc); /* Do we have enough space to put number with * required width ? */ @@ -192,16 +191,16 @@ /* Left precision */ if (*fmt == '#') { - if (!isdigit((unsigned char)*++fmt)) + if (!isdigit_l((unsigned char)*++fmt, loc)) goto format_error; - GET_NUMBER(left_prec); + GET_NUMBER(left_prec, loc); } /* Right precision */ if (*fmt == '.') { - if (!isdigit((unsigned char)*++fmt)) + if (!isdigit_l((unsigned char)*++fmt, loc)) goto format_error; - GET_NUMBER(right_prec); + GET_NUMBER(right_prec, loc); } /* Conversion Characters */ @@ -239,21 +238,21 @@ /* fill left_prec with amount of padding chars */ if (left_prec >= 0) { pad_size = __calc_left_pad((flags ^ IS_NEGATIVE), - currency_symbol) - - __calc_left_pad(flags, currency_symbol); + currency_symbol, lc) - + __calc_left_pad(flags, currency_symbol, lc); if (pad_size < 0) pad_size = 0; } asciivalue = __format_grouped_double(value, &flags, - left_prec, right_prec, pad_char); + left_prec, right_prec, pad_char, lc, loc); 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, - &sign_posn, &signstr); + &sign_posn, &signstr, lc); /* * Description of some LC_MONETARY's values: @@ -366,7 +365,6 @@ } PRINT('\0'); - va_end(ap); free(asciivalue); free(currency_symbol); return (dst - s - 1); /* return size of put data except trailing '\0' */ @@ -385,15 +383,12 @@ 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, - char *sign_posn, char **signstr) { - - struct lconv *lc = localeconv(); + char *sign_posn, char **signstr, struct lconv *lc) { if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) { *cs_precedes = lc->int_n_cs_precedes; @@ -429,12 +424,12 @@ } static int -__calc_left_pad(int flags, char *cur_symb) { +__calc_left_pad(int flags, char *cur_symb, struct lconv *lc) { char cs_precedes, sep_by_space, sign_posn, *signstr; int left_chars = 0; - __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr); + __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr, lc); if (cs_precedes != 0) { left_chars += strlen(cur_symb); @@ -480,7 +475,7 @@ /* convert double to ASCII */ static char * __format_grouped_double(double value, int *flags, - int left_prec, int right_prec, int pad_char) { + int left_prec, int right_prec, int pad_char, struct lconv *lc, locale_t loc) { char *rslt; char *avalue; @@ -492,7 +487,6 @@ int padded; - struct lconv *lc = localeconv(); char *grouping; char decimal_point; char thousands_sep; @@ -526,9 +520,9 @@ left_prec += get_groups(left_prec, grouping); /* convert to string */ - snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1, + snprintf_l(fmt, sizeof(fmt), loc, "%%%d.%df", left_prec + right_prec + 1, right_prec); - avalue_size = asprintf(&avalue, fmt, value); + avalue_size = asprintf_l(&avalue, loc, fmt, value); if (avalue_size < 0) return (NULL); @@ -601,3 +595,30 @@ free(avalue); return (rslt); } + +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, format); + ret = _strfmon(s, maxsize, __current_locale(), format, ap); + va_end(ap); + return ret; +} + +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, + const char * __restrict format, ...) +{ + ssize_t ret; + va_list ap; + + NORMALIZE_LOCALE(loc); + va_start(ap, format); + ret = _strfmon(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +}