]>
Commit | Line | Data |
---|---|---|
b5d655f7 A |
1 | --- strfmon.c.orig 2008-04-04 21:54:54.000000000 -0700 |
2 | +++ strfmon.c 2008-04-04 22:11:39.000000000 -0700 | |
3 | @@ -41,6 +41,8 @@ __RCSID("$NetBSD: strfmon.c,v 1.6 2008/0 | |
4 | #include <monetary.h> | |
5 | #endif | |
3d9156a7 A |
6 | |
7 | +#include "xlocale_private.h" | |
8 | + | |
9 | #include <sys/types.h> | |
10 | #include <ctype.h> | |
11 | #include <errno.h> | |
b5d655f7 | 12 | @@ -75,9 +77,9 @@ __RCSID("$NetBSD: strfmon.c,v 1.6 2008/0 |
3d9156a7 | 13 | PRINT(*tmps++); \ |
b5d655f7 | 14 | } while (/* CONSTCOND */ 0) |
3d9156a7 A |
15 | |
16 | -#define GET_NUMBER(VAR) do { \ | |
17 | +#define GET_NUMBER(VAR,LOC) do { \ | |
18 | VAR = 0; \ | |
19 | - while (isdigit((unsigned char)*fmt)) { \ | |
20 | + while (isdigit_l((unsigned char)*fmt, (LOC))) { \ | |
21 | VAR *= 10; \ | |
22 | VAR += *fmt - '0'; \ | |
b5d655f7 A |
23 | if (VAR > 0x00ffffff) \ |
24 | @@ -99,15 +101,13 @@ __RCSID("$NetBSD: strfmon.c,v 1.6 2008/0 | |
3d9156a7 | 25 | groups++; \ |
b5d655f7 | 26 | } while (/* CONSTCOND */ 0) |
3d9156a7 | 27 | |
b5d655f7 | 28 | -static void __setup_vars(int, char *, char *, char *, const char **); |
3d9156a7 A |
29 | -static int __calc_left_pad(int, char *); |
30 | -static char *__format_grouped_double(double, int *, int, int, int); | |
b5d655f7 A |
31 | +static void __setup_vars(int, char *, char *, char *, const char **, struct lconv *); |
32 | +static int __calc_left_pad(int, char *, struct lconv *); | |
33 | +static char *__format_grouped_double(double, int *, int, int, int, struct lconv *, locale_t); | |
34 | ||
3d9156a7 A |
35 | -ssize_t |
36 | -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, | |
37 | - ...) | |
3d9156a7 | 38 | +static ssize_t |
b5d655f7 | 39 | +_strfmon(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, va_list ap) |
3d9156a7 A |
40 | { |
41 | - va_list ap; | |
42 | char *dst; /* output destination pointer */ | |
43 | const char *fmt; /* current format poistion pointer */ | |
44 | struct lconv *lc; /* pointer to lconv structure */ | |
b5d655f7 | 45 | @@ -131,9 +131,7 @@ strfmon(char * __restrict s, size_t maxs |
3d9156a7 A |
46 | char *tmpptr; /* temporary vars */ |
47 | int sverrno; | |
48 | ||
49 | - va_start(ap, format); | |
50 | - | |
51 | - lc = localeconv(); | |
52 | + lc = localeconv_l(loc); | |
53 | dst = s; | |
54 | fmt = format; | |
55 | asciivalue = NULL; | |
b5d655f7 | 56 | @@ -197,9 +195,9 @@ strfmon(char * __restrict s, size_t maxs |
3d9156a7 A |
57 | } |
58 | ||
59 | /* field Width */ | |
60 | - if (isdigit((unsigned char)*fmt)) { | |
3d9156a7 | 61 | + if (isdigit_l((unsigned char)*fmt, loc)) { |
b5d655f7 A |
62 | ptrdiff_t d = dst - s; |
63 | - GET_NUMBER(width); | |
3d9156a7 A |
64 | + GET_NUMBER(width, loc); |
65 | /* Do we have enough space to put number with | |
66 | * required width ? | |
67 | */ | |
b5d655f7 | 68 | @@ -210,16 +208,16 @@ strfmon(char * __restrict s, size_t maxs |
3d9156a7 A |
69 | |
70 | /* Left precision */ | |
71 | if (*fmt == '#') { | |
72 | - if (!isdigit((unsigned char)*++fmt)) | |
73 | + if (!isdigit_l((unsigned char)*++fmt, loc)) | |
74 | goto format_error; | |
75 | - GET_NUMBER(left_prec); | |
76 | + GET_NUMBER(left_prec, loc); | |
77 | } | |
78 | ||
79 | /* Right precision */ | |
80 | if (*fmt == '.') { | |
81 | - if (!isdigit((unsigned char)*++fmt)) | |
82 | + if (!isdigit_l((unsigned char)*++fmt, loc)) | |
83 | goto format_error; | |
84 | - GET_NUMBER(right_prec); | |
85 | + GET_NUMBER(right_prec, loc); | |
86 | } | |
87 | ||
88 | /* Conversion Characters */ | |
b5d655f7 A |
89 | @@ -239,8 +237,10 @@ strfmon(char * __restrict s, size_t maxs |
90 | free(currency_symbol); | |
224c7076 A |
91 | if (flags & USE_INTL_CURRENCY) { |
92 | currency_symbol = strdup(lc->int_curr_symbol); | |
93 | - if (currency_symbol != NULL) | |
94 | + if (currency_symbol != NULL) { | |
95 | space_char = *(currency_symbol+3); | |
96 | + currency_symbol[3] = '\0'; | |
97 | + } | |
98 | } else | |
99 | currency_symbol = strdup(lc->currency_symbol); | |
100 | ||
b5d655f7 | 101 | @@ -259,21 +259,21 @@ strfmon(char * __restrict s, size_t maxs |
3d9156a7 A |
102 | /* fill left_prec with amount of padding chars */ |
103 | if (left_prec >= 0) { | |
104 | pad_size = __calc_left_pad((flags ^ IS_NEGATIVE), | |
105 | - currency_symbol) - | |
106 | - __calc_left_pad(flags, currency_symbol); | |
107 | + currency_symbol, lc) - | |
108 | + __calc_left_pad(flags, currency_symbol, lc); | |
109 | if (pad_size < 0) | |
110 | pad_size = 0; | |
111 | } | |
112 | ||
113 | asciivalue = __format_grouped_double(value, &flags, | |
114 | - left_prec, right_prec, pad_char); | |
115 | + left_prec, right_prec, pad_char, lc, loc); | |
116 | if (asciivalue == NULL) | |
117 | goto end_error; /* errno already set */ | |
118 | /* to ENOMEM by malloc() */ | |
119 | ||
120 | /* set some variables for later use */ | |
121 | __setup_vars(flags, &cs_precedes, &sep_by_space, | |
122 | - &sign_posn, &signstr); | |
123 | + &sign_posn, &signstr, lc); | |
124 | ||
125 | /* | |
126 | * Description of some LC_MONETARY's values: | |
b5d655f7 | 127 | @@ -333,8 +333,11 @@ strfmon(char * __restrict s, size_t maxs |
224c7076 A |
128 | } else if (sep_by_space == 1) |
129 | PRINT(space_char); | |
130 | } | |
131 | - } else if (sign_posn == 1) | |
132 | + } else if (sign_posn == 1) { | |
133 | PRINTS(signstr); | |
134 | + if (sep_by_space == 2) | |
135 | + PRINT(' '); | |
136 | + } | |
137 | ||
138 | PRINTS(asciivalue); | |
139 | ||
b5d655f7 | 140 | @@ -368,8 +371,12 @@ strfmon(char * __restrict s, size_t maxs |
224c7076 A |
141 | PRINTS(signstr); |
142 | } | |
143 | ||
144 | - if (sign_posn == 0 && (flags & IS_NEGATIVE)) | |
145 | - PRINT(')'); | |
146 | + if (sign_posn == 0) { | |
147 | + if (flags & IS_NEGATIVE) | |
148 | + PRINT(')'); | |
149 | + else if (left_prec >= 0) | |
150 | + PRINT(' '); | |
151 | + } | |
152 | ||
153 | if (dst - tmpptr < width) { | |
154 | if (flags & LEFT_JUSTIFY) { | |
b5d655f7 | 155 | @@ -386,7 +393,6 @@ strfmon(char * __restrict s, size_t maxs |
3d9156a7 A |
156 | } |
157 | ||
158 | PRINT('\0'); | |
159 | - va_end(ap); | |
160 | free(asciivalue); | |
161 | free(currency_symbol); | |
162 | return (dst - s - 1); /* return size of put data except trailing '\0' */ | |
b5d655f7 | 163 | @@ -405,14 +411,12 @@ end_error: |
3d9156a7 A |
164 | if (currency_symbol != NULL) |
165 | free(currency_symbol); | |
166 | errno = sverrno; | |
167 | - va_end(ap); | |
168 | return (-1); | |
169 | } | |
170 | ||
171 | static void | |
172 | __setup_vars(int flags, char *cs_precedes, char *sep_by_space, | |
b5d655f7 | 173 | - char *sign_posn, const char **signstr) { |
3d9156a7 | 174 | - struct lconv *lc = localeconv(); |
b5d655f7 | 175 | + char *sign_posn, const char **signstr, struct lconv *lc) { |
3d9156a7 A |
176 | |
177 | if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) { | |
178 | *cs_precedes = lc->int_n_cs_precedes; | |
b5d655f7 | 179 | @@ -448,13 +452,13 @@ __setup_vars(int flags, char *cs_precede |
3d9156a7 A |
180 | } |
181 | ||
182 | static int | |
183 | -__calc_left_pad(int flags, char *cur_symb) { | |
184 | +__calc_left_pad(int flags, char *cur_symb, struct lconv *lc) { | |
185 | ||
b5d655f7 A |
186 | char cs_precedes, sep_by_space, sign_posn; |
187 | const char *signstr; | |
3d9156a7 A |
188 | int left_chars = 0; |
189 | ||
190 | - __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr); | |
191 | + __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr, lc); | |
192 | ||
193 | if (cs_precedes != 0) { | |
194 | left_chars += strlen(cur_symb); | |
b5d655f7 | 195 | @@ -463,6 +467,10 @@ __calc_left_pad(int flags, char *cur_sym |
224c7076 A |
196 | } |
197 | ||
198 | switch (sign_posn) { | |
199 | + case 0: | |
200 | + if (flags & IS_NEGATIVE) | |
201 | + left_chars++; | |
202 | + break; | |
203 | case 1: | |
204 | left_chars += strlen(signstr); | |
205 | break; | |
b5d655f7 | 206 | @@ -498,9 +506,11 @@ get_groups(int size, char *grouping) { |
224c7076 A |
207 | } |
208 | ||
3d9156a7 | 209 | /* convert double to ASCII */ |
224c7076 A |
210 | +__private_extern__ const char *__fix_nogrouping(const char *); |
211 | + | |
3d9156a7 A |
212 | static char * |
213 | __format_grouped_double(double value, int *flags, | |
214 | - int left_prec, int right_prec, int pad_char) { | |
215 | + int left_prec, int right_prec, int pad_char, struct lconv *lc, locale_t loc) { | |
216 | ||
217 | char *rslt; | |
218 | char *avalue; | |
b5d655f7 | 219 | @@ -512,14 +522,13 @@ __format_grouped_double(double value, in |
3d9156a7 A |
220 | |
221 | int padded; | |
222 | ||
223 | - struct lconv *lc = localeconv(); | |
224 | char *grouping; | |
225 | char decimal_point; | |
226 | char thousands_sep; | |
224c7076 A |
227 | |
228 | int groups = 0; | |
229 | ||
230 | - grouping = lc->mon_grouping; | |
231 | + grouping = __fix_nogrouping(lc->mon_grouping); | |
232 | decimal_point = *lc->mon_decimal_point; | |
233 | if (decimal_point == '\0') | |
234 | decimal_point = *lc->decimal_point; | |
b5d655f7 | 235 | @@ -546,9 +555,9 @@ __format_grouped_double(double value, in |
3d9156a7 A |
236 | left_prec += get_groups(left_prec, grouping); |
237 | ||
238 | /* convert to string */ | |
239 | - snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1, | |
240 | + snprintf_l(fmt, sizeof(fmt), loc, "%%%d.%df", left_prec + right_prec + 1, | |
241 | right_prec); | |
242 | - avalue_size = asprintf(&avalue, fmt, value); | |
243 | + avalue_size = asprintf_l(&avalue, loc, fmt, value); | |
244 | if (avalue_size < 0) | |
245 | return (NULL); | |
246 | ||
b5d655f7 | 247 | @@ -621,3 +630,30 @@ __format_grouped_double(double value, in |
3d9156a7 A |
248 | free(avalue); |
249 | return (rslt); | |
250 | } | |
251 | + | |
252 | +ssize_t | |
253 | +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, | |
254 | + ...) | |
255 | +{ | |
256 | + ssize_t ret; | |
257 | + va_list ap; | |
258 | + | |
259 | + va_start(ap, format); | |
260 | + ret = _strfmon(s, maxsize, __current_locale(), format, ap); | |
261 | + va_end(ap); | |
262 | + return ret; | |
263 | +} | |
264 | + | |
265 | +ssize_t | |
266 | +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, | |
267 | + const char * __restrict format, ...) | |
268 | +{ | |
269 | + ssize_t ret; | |
270 | + va_list ap; | |
271 | + | |
272 | + NORMALIZE_LOCALE(loc); | |
273 | + va_start(ap, format); | |
274 | + ret = _strfmon(s, maxsize, loc, format, ap); | |
275 | + va_end(ap); | |
276 | + return ret; | |
277 | +} |