From 765d2c0bac08a62ef576f3813a2ed1f4e04724f5 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 25 Jul 2016 11:26:08 +0200 Subject: [PATCH] Implement strfmon_l Use latest code from FreeBSD Signed-off by: Corinna Vinschen --- winsup/cygwin/common.din | 1 + winsup/cygwin/libc/strfmon.c | 97 +++++++++++++++++++++++------------- winsup/doc/posix.xml | 2 +- 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index 114adc95c..2cc826459 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -1344,6 +1344,7 @@ strdup SIGFE strerror SIGFE strerror_r SIGFE strfmon SIGFE +strfmon_l SIGFE strftime SIGFE strftime_l SIGFE strlcat NOSIGFE diff --git a/winsup/cygwin/libc/strfmon.c b/winsup/cygwin/libc/strfmon.c index 91f0f8442..533fc2121 100644 --- a/winsup/cygwin/libc/strfmon.c +++ b/winsup/cygwin/libc/strfmon.c @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,12 +30,10 @@ * */ -#if 0 -__FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.19 2008/04/24 07:49:00 ru Exp $"); -#endif - -#include "winsup.h" +#define _GNU_SOURCE #include +__FBSDID("$FreeBSD$"); + #include #include #include @@ -41,13 +44,21 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.19 2008/04/24 07:49:00 ru #include #include #include +#ifndef __CYGWIN__ +#include "xlocale_private.h" +#else +#include "../locale/setlocale.h" +#define __get_locale() __get_current_locale() +#define FIX_LOCALE(__l) +#define localeconv_l __localeconv_l +#endif /* internal flags */ #define NEED_GROUPING 0x01 /* print digits grouped (default) */ #define SIGN_POSN_USED 0x02 /* '+' or '(' usage flag */ #define LOCALE_POSN 0x04 /* use locale defined +/- (default) */ #define PARENTH_POSN 0x08 /* enclose negative amount in () */ -#define SUPRESS_CURR_SYMBOL 0x10 /* supress the currency from output */ +#define SUPRESS_CURR_SYMBOL 0x10 /* suppress the currency from output */ #define LEFT_JUSTIFY 0x20 /* left justify */ #define USE_INTL_CURRENCY 0x40 /* use international currency symbol */ #define IS_NEGATIVE 0x80 /* is argument value negative ? */ @@ -95,11 +106,10 @@ 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 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 */ @@ -122,10 +132,10 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, char *tmpptr; /* temporary vars */ int sverrno; + FIX_LOCALE(loc); - va_start(ap, format); - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -234,10 +244,8 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, free(currency_symbol); if (flags & USE_INTL_CURRENCY) { currency_symbol = strdup(lc->int_curr_symbol); - if (currency_symbol != NULL) { + if (currency_symbol != NULL) space_char = *(currency_symbol+3); - *(currency_symbol+3) = '\0'; - } } else currency_symbol = strdup(lc->currency_symbol); @@ -296,9 +304,9 @@ strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, * * = 0 - parentheses enclose the quantity and the * $currency_symbol - * = 1 - the sign string precedes the quantity and the + * = 1 - the sign string precedes the quantity and the * $currency_symbol - * = 2 - the sign string succeeds the quantity and the + * = 2 - the sign string succeeds the quantity and the * $currency_symbol * = 3 - the sign string precedes the $currency_symbol * = 4 - the sign string succeeds the $currency_symbol @@ -385,7 +393,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' */ @@ -404,39 +411,61 @@ end_error: if (currency_symbol != NULL) free(currency_symbol); errno = sverrno; - va_end(ap); return (-1); } +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +} + +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap); + va_end(ap); + return ret; +} + static void __setup_vars(int flags, char *cs_precedes, char *sep_by_space, char *sign_posn, char **signstr) { struct lconv *lc = localeconv(); - static char negative[] = "-"; if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) { *cs_precedes = lc->int_n_cs_precedes; *sep_by_space = lc->int_n_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn; - *signstr = (*lc->negative_sign == '\0') ? negative - : lc->negative_sign; + *sign_posn = (char) ((flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn); + *signstr = (char *) ((lc->negative_sign[0] == '\0') ? "-" + : lc->negative_sign); } else if (flags & USE_INTL_CURRENCY) { *cs_precedes = lc->int_p_cs_precedes; *sep_by_space = lc->int_p_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_p_sign_posn; + *sign_posn = (char) ((flags & PARENTH_POSN) ? 0 : lc->int_p_sign_posn); *signstr = lc->positive_sign; } else if (flags & IS_NEGATIVE) { *cs_precedes = lc->n_cs_precedes; *sep_by_space = lc->n_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn; - *signstr = (*lc->negative_sign == '\0') ? negative - : lc->negative_sign; + *sign_posn = (char) ((flags & PARENTH_POSN) ? 0 : lc->n_sign_posn); + *signstr = (char *) ((lc->negative_sign[0] == '\0') ? "-" + : lc->negative_sign); } else { *cs_precedes = lc->p_cs_precedes; *sep_by_space = lc->p_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->p_sign_posn; - *signstr = lc->positive_sign; + *sign_posn = (char) ((flags & PARENTH_POSN) ? 0 : lc->p_sign_posn); + *signstr = (char *) lc->positive_sign; } /* Set defult values for unspecified information. */ @@ -505,7 +534,6 @@ __format_grouped_double(double value, int *flags, char *rslt; char *avalue; int avalue_size; - char fmt[32]; size_t bufsize; char *bufend; @@ -546,14 +574,13 @@ __format_grouped_double(double value, int *flags, left_prec += get_groups(left_prec, grouping); /* convert to string */ - snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1, - right_prec); - avalue_size = asprintf(&avalue, fmt, value); + avalue_size = asprintf(&avalue, "%*.*f", left_prec + right_prec + 1, + right_prec, value); if (avalue_size < 0) return (NULL); /* make sure that we've enough space for result string */ - bufsize = strlen(avalue)*2+1; + bufsize = avalue_size * 2 + 1; rslt = calloc(1, bufsize); if (rslt == NULL) { free(avalue); @@ -561,7 +588,7 @@ __format_grouped_double(double value, int *flags, } bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */ - /* skip spaces at beggining */ + /* skip spaces at beginning */ padded = 0; while (avalue[padded] == ' ') { padded++; diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index bc38f3920..48499fb4e 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -925,6 +925,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). strerror strerror_r strfmon + strfmon_l strftime strftime_l strlen @@ -1548,7 +1549,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). putmsg setnetent sigtimedwait - strfmon_l timer_getoverrun ulimit waitid