2
2
*
3
3
* PostgreSQL locale utilities
4
4
*
5
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.17 2002/05/17 01:19:18 tgl Exp $
5
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.18 2002/08/09 22:52:04 petere Exp $
6
6
*
7
7
* Portions Copyright (c) 2002, PostgreSQL Global Development Group
8
8
*
9
9
*-----------------------------------------------------------------------
10
10
*/
11
11
12
+ /*
13
+ * Here is how the locale stuff is handled: LC_COLLATE and LC_CTYPE
14
+ * are fixed by initdb, stored in pg_control, and cannot be changed.
15
+ * Thus, the effects of strcoll(), strxfrm(), isupper(), toupper(),
16
+ * etc. are always in the same fixed locale.
17
+ *
18
+ * LC_MESSAGES is settable at run time and will take effect
19
+ * immediately.
20
+ *
21
+ * The other categories, LC_MONETARY, LC_NUMERIC, and LC_TIME are also
22
+ * settable at run-time. However, we don't actually set those locale
23
+ * categories permanently. This would have bizzare effects like no
24
+ * longer accepting standard floating-point literals in some locales.
25
+ * Instead, we only set the locales briefly when needed, cache the
26
+ * required information obtained from localeconv(), and set them back.
27
+ * The information is only used by the formatting functions (to_char,
28
+ * etc.) and the money type. For the user, this should all be
29
+ * transparent. (Actually, LC_TIME doesn't do anything at all right
30
+ * now.)
31
+ */
32
+
33
+
12
34
#include "postgres.h"
13
35
14
36
#include <locale.h>
15
37
16
38
#include "utils/pg_locale.h"
17
39
18
40
41
+ /* indicated whether locale information cache is valid */
42
+ static bool CurrentLocaleConvValid = false;
43
+
44
+
19
45
/* GUC storage area */
20
46
21
47
char * locale_messages ;
@@ -26,41 +52,33 @@ char *locale_time;
26
52
27
53
/* GUC assign hooks */
28
54
55
+ /*
56
+ * This is common code for several locale categories. This doesn't
57
+ * actually set the locale permanently, it only tests if the locale is
58
+ * valid. (See explanation at the top of this file.)
59
+ */
29
60
static const char *
30
61
locale_xxx_assign (int category , const char * value , bool doit , bool interactive )
31
62
{
32
- if (doit )
33
- {
34
- if (!setlocale (category , value ))
35
- return NULL ;
36
- }
37
- else
38
- {
39
- char * save ;
63
+ char * save ;
40
64
41
- save = setlocale (category , NULL );
42
- if (!save )
43
- return NULL ;
65
+ save = setlocale (category , NULL );
66
+ if (!save )
67
+ return NULL ;
44
68
45
- if (!setlocale (category , value ))
46
- return NULL ;
69
+ if (!setlocale (category , value ))
70
+ return NULL ;
47
71
48
- setlocale (category , save );
49
- }
50
- return value ;
51
- }
72
+ setlocale (category , save );
73
+
74
+ /* need to reload cache next time */
75
+ if (doit )
76
+ CurrentLocaleConvValid = false;
52
77
53
- const char *
54
- locale_messages_assign (const char * value , bool doit , bool interactive )
55
- {
56
- /* LC_MESSAGES category does not exist everywhere, but accept it anyway */
57
- #ifdef LC_MESSAGES
58
- return locale_xxx_assign (LC_MESSAGES , value , doit , interactive );
59
- #else
60
78
return value ;
61
- #endif
62
79
}
63
80
81
+
64
82
const char *
65
83
locale_monetary_assign (const char * value , bool doit , bool interactive )
66
84
{
@@ -80,6 +98,37 @@ locale_time_assign(const char *value, bool doit, bool interactive)
80
98
}
81
99
82
100
101
+ /*
102
+ * lc_messages takes effect immediately
103
+ */
104
+ const char *
105
+ locale_messages_assign (const char * value , bool doit , bool interactive )
106
+ {
107
+ /* LC_MESSAGES category does not exist everywhere, but accept it anyway */
108
+ #ifdef LC_MESSAGES
109
+ if (doit )
110
+ {
111
+ if (!setlocale (LC_MESSAGES , value ))
112
+ return NULL ;
113
+ }
114
+ else
115
+ {
116
+ char * save ;
117
+
118
+ save = setlocale (LC_MESSAGES , NULL );
119
+ if (!save )
120
+ return NULL ;
121
+
122
+ if (!setlocale (LC_MESSAGES , value ))
123
+ return NULL ;
124
+
125
+ setlocale (LC_MESSAGES , save );
126
+ }
127
+ #endif
128
+ return value ;
129
+ }
130
+
131
+
83
132
/*
84
133
* We'd like to cache whether LC_COLLATE is C (or POSIX), so we can
85
134
* optimize a few code paths in various places.
@@ -107,23 +156,64 @@ lc_collate_is_c(void)
107
156
}
108
157
109
158
159
+ /*
160
+ * Frees the malloced content of a struct lconv. (But not the struct
161
+ * itself.)
162
+ */
163
+ static void
164
+ free_struct_lconv (struct lconv * s )
165
+ {
166
+ if (s == NULL )
167
+ return ;
168
+
169
+ if (s -> currency_symbol )
170
+ free (s -> currency_symbol );
171
+ if (s -> decimal_point )
172
+ free (s -> decimal_point );
173
+ if (s -> grouping )
174
+ free (s -> grouping );
175
+ if (s -> thousands_sep )
176
+ free (s -> thousands_sep );
177
+ if (s -> int_curr_symbol )
178
+ free (s -> int_curr_symbol );
179
+ if (s -> mon_decimal_point )
180
+ free (s -> mon_decimal_point );
181
+ if (s -> mon_grouping )
182
+ free (s -> mon_grouping );
183
+ if (s -> mon_thousands_sep )
184
+ free (s -> mon_thousands_sep );
185
+ if (s -> negative_sign )
186
+ free (s -> negative_sign );
187
+ if (s -> positive_sign )
188
+ free (s -> positive_sign );
189
+ }
190
+
191
+
110
192
/*
111
193
* Return the POSIX lconv struct (contains number/money formatting
112
194
* information) with locale information for all categories.
113
195
*/
114
196
struct lconv *
115
197
PGLC_localeconv (void )
116
198
{
117
- static bool CurrentLocaleConvValid = false;
118
199
static struct lconv CurrentLocaleConv ;
119
-
120
200
struct lconv * extlconv ;
201
+ char * save_lc_monetary ;
202
+ char * save_lc_numeric ;
121
203
122
204
/* Did we do it already? */
123
205
if (CurrentLocaleConvValid )
124
206
return & CurrentLocaleConv ;
125
207
126
- /* Get formatting information for the external environment */
208
+ free_struct_lconv (& CurrentLocaleConv );
209
+
210
+ save_lc_monetary = setlocale (LC_MONETARY , NULL );
211
+ save_lc_numeric = setlocale (LC_NUMERIC , NULL );
212
+
213
+ setlocale (LC_MONETARY , locale_monetary );
214
+ setlocale (LC_NUMERIC , locale_numeric );
215
+
216
+ /* Get formatting information */
127
217
extlconv = localeconv ();
128
218
129
219
/*
@@ -141,6 +231,10 @@ PGLC_localeconv(void)
141
231
CurrentLocaleConv .mon_thousands_sep = strdup (extlconv -> mon_thousands_sep );
142
232
CurrentLocaleConv .negative_sign = strdup (extlconv -> negative_sign );
143
233
CurrentLocaleConv .positive_sign = strdup (extlconv -> positive_sign );
234
+ CurrentLocaleConv .n_sign_posn = extlconv -> n_sign_posn ;
235
+
236
+ setlocale (LC_MONETARY , save_lc_monetary );
237
+ setlocale (LC_NUMERIC , save_lc_numeric );
144
238
145
239
CurrentLocaleConvValid = true;
146
240
return & CurrentLocaleConv ;
0 commit comments