9
9
* workings can be found in the book "Software Solutions in C" by
10
10
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
11
11
*
12
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.45 2000/08/03 16:34:22 tgl Exp $
12
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.46 2000/11/18 03:55:51 tgl Exp $
13
13
*/
14
14
15
15
#include <limits.h>
@@ -91,9 +91,19 @@ cash_in(PG_FUNCTION_ARGS)
91
91
if (lconvert == NULL )
92
92
lconvert = localeconv ();
93
93
94
- /* frac_digits in the C locale seems to return CHAR_MAX */
95
- /* best guess is 2 in this case I think */
96
- fpoint = ((lconvert -> frac_digits != (char )CHAR_MAX ) ? lconvert -> frac_digits : 2 ); /* int_frac_digits? */
94
+ /*
95
+ * frac_digits will be CHAR_MAX in some locales, notably C. However,
96
+ * just testing for == CHAR_MAX is risky, because of compilers like
97
+ * gcc that "helpfully" let you alter the platform-standard definition
98
+ * of whether char is signed or not. If we are so unfortunate as to
99
+ * get compiled with a nonstandard -fsigned-char or -funsigned-char
100
+ * switch, then our idea of CHAR_MAX will not agree with libc's.
101
+ * The safest course is not to test for CHAR_MAX at all, but to impose
102
+ * a range check for plausible frac_digits values.
103
+ */
104
+ fpoint = lconvert -> frac_digits ;
105
+ if (fpoint < 0 || fpoint > 10 )
106
+ fpoint = 2 ; /* best guess in this case, I think */
97
107
98
108
dsymbol = ((* lconvert -> mon_decimal_point != '\0' ) ? * lconvert -> mon_decimal_point : '.' );
99
109
ssymbol = ((* lconvert -> mon_thousands_sep != '\0' ) ? * lconvert -> mon_thousands_sep : ',' );
@@ -225,9 +235,9 @@ cash_out(PG_FUNCTION_ARGS)
225
235
int count = LAST_DIGIT ;
226
236
int point_pos ;
227
237
int comma_position = 0 ;
228
- char mon_group ,
229
- comma ,
230
- points ;
238
+ int points ,
239
+ mon_group ;
240
+ char comma ;
231
241
char * csymbol ,
232
242
dsymbol ,
233
243
* nsymbol ;
@@ -237,32 +247,36 @@ cash_out(PG_FUNCTION_ARGS)
237
247
if (lconvert == NULL )
238
248
lconvert = localeconv ();
239
249
250
+ /* see comments about frac_digits in cash_in() */
251
+ points = lconvert -> frac_digits ;
252
+ if (points < 0 || points > 10 )
253
+ points = 2 ; /* best guess in this case, I think */
254
+
255
+ /*
256
+ * As with frac_digits, must apply a range check to mon_grouping
257
+ * to avoid being fooled by variant CHAR_MAX values.
258
+ */
240
259
mon_group = * lconvert -> mon_grouping ;
260
+ if (mon_group <= 0 || mon_group > 6 )
261
+ mon_group = 3 ;
262
+
241
263
comma = ((* lconvert -> mon_thousands_sep != '\0' ) ? * lconvert -> mon_thousands_sep : ',' );
242
- /* frac_digits in the C locale seems to return CHAR_MAX */
243
- /* best guess is 2 in this case I think */
244
- points = ((lconvert -> frac_digits != (char )CHAR_MAX ) ? lconvert -> frac_digits : 2 ); /* int_frac_digits? */
245
264
convention = lconvert -> n_sign_posn ;
246
265
dsymbol = ((* lconvert -> mon_decimal_point != '\0' ) ? * lconvert -> mon_decimal_point : '.' );
247
266
csymbol = ((* lconvert -> currency_symbol != '\0' ) ? lconvert -> currency_symbol : "$" );
248
267
nsymbol = ((* lconvert -> negative_sign != '\0' ) ? lconvert -> negative_sign : "-" );
249
268
#else
269
+ points = 2 ;
250
270
mon_group = 3 ;
251
271
comma = ',' ;
252
- csymbol = "$" ;
272
+ convention = 0 ;
253
273
dsymbol = '.' ;
274
+ csymbol = "$" ;
254
275
nsymbol = "-" ;
255
- points = 2 ;
256
- convention = 0 ;
257
276
#endif
258
277
259
278
point_pos = LAST_DIGIT - points ;
260
279
261
- /* We're playing a little fast and loose with this. Shoot me. */
262
- /* Not me, that was the other guy. Haven't fixed it yet - thomas */
263
- if (!mon_group || mon_group == (char )CHAR_MAX )
264
- mon_group = 3 ;
265
-
266
280
/* allow more than three decimal points and separate them */
267
281
if (comma )
268
282
{
0 commit comments