4
4
* The PostgreSQL locale utils.
5
5
*
6
6
*
7
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.9 2001/03/22 03:59:52 momjian Exp $
7
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.10 2001/09/29 21:16:30 tgl Exp $
8
8
*
9
9
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
10
10
*
11
- * Karel Zak - Zakkr
11
+ * Karel Zak
12
12
*
13
13
* -----------------------------------------------------------------------
14
14
*/
18
18
#ifdef USE_LOCALE
19
19
20
20
#include <locale.h>
21
+
21
22
#include "utils/pg_locale.h"
22
23
23
24
/* #define DEBUG_LOCALE_UTILS */
24
25
25
26
26
- static struct lconv * CurrentLocaleConv = NULL ;
27
+ static bool CurrentLocaleConvValid = false;
28
+ static struct lconv CurrentLocaleConv ;
29
+
27
30
28
31
static void PGLC_setlocale (PG_LocaleCategories * lc );
29
32
30
33
/*------
31
- * Return in PG_LocaleCategories the current locale settings
34
+ * Frees memory used in PG_LocaleCategories -- this memory is
35
+ * allocated in PGLC_current().
36
+ *------
37
+ */
38
+ void
39
+ PGLC_free_categories (PG_LocaleCategories * lc )
40
+ {
41
+ if (lc -> lc_ctype )
42
+ pfree (lc -> lc_ctype );
43
+ if (lc -> lc_numeric )
44
+ pfree (lc -> lc_numeric );
45
+ if (lc -> lc_time )
46
+ pfree (lc -> lc_time );
47
+ if (lc -> lc_collate )
48
+ pfree (lc -> lc_collate );
49
+ if (lc -> lc_monetary );
50
+ pfree (lc -> lc_monetary );
51
+ #ifdef LC_MESSAGES
52
+ if (lc -> lc_messages )
53
+ pfree (lc -> lc_messages );
54
+ #endif
55
+ }
56
+
57
+ /*------
58
+ * Return in PG_LocaleCategories the current locale settings.
59
+ *
60
+ * NB: strings are allocated in the current memory context!
32
61
*------
33
62
*/
34
63
void
35
64
PGLC_current (PG_LocaleCategories * lc )
36
65
{
37
66
lc -> lang = getenv ("LANG" );
38
67
39
- lc -> lc_ctype = setlocale (LC_CTYPE , NULL );
40
- lc -> lc_numeric = setlocale (LC_NUMERIC , NULL );
41
- lc -> lc_time = setlocale (LC_TIME , NULL );
42
- lc -> lc_collate = setlocale (LC_COLLATE , NULL );
43
- lc -> lc_monetary = setlocale (LC_MONETARY , NULL );
68
+ lc -> lc_ctype = pstrdup ( setlocale (LC_CTYPE , NULL ) );
69
+ lc -> lc_numeric = pstrdup ( setlocale (LC_NUMERIC , NULL ) );
70
+ lc -> lc_time = pstrdup ( setlocale (LC_TIME , NULL ) );
71
+ lc -> lc_collate = pstrdup ( setlocale (LC_COLLATE , NULL ) );
72
+ lc -> lc_monetary = pstrdup ( setlocale (LC_MONETARY , NULL ) );
44
73
#ifdef LC_MESSAGES
45
- lc -> lc_messages = setlocale (LC_MESSAGES , NULL );
74
+ lc -> lc_messages = pstrdup ( setlocale (LC_MESSAGES , NULL ) );
46
75
#endif
47
76
}
48
77
@@ -58,19 +87,22 @@ PGLC_debug_lc(PG_LocaleCategories * lc)
58
87
{
59
88
#ifdef LC_MESSAGES
60
89
elog (DEBUG , "CURRENT LOCALE ENVIRONMENT:\n\nLANG: \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\nLC_MESSAGES:\t%s\n" ,
90
+ lc -> lang ,
91
+ lc -> lc_ctype ,
92
+ lc -> lc_numeric ,
93
+ lc -> lc_time ,
94
+ lc -> lc_collate ,
95
+ lc -> lc_monetary ,
96
+ lc -> lc_messages );
61
97
#else
62
98
elog (DEBUG , "CURRENT LOCALE ENVIRONMENT:\n\nLANG: \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\n" ,
63
- #endif
64
99
lc -> lang ,
65
100
lc -> lc_ctype ,
66
101
lc -> lc_numeric ,
67
102
lc -> lc_time ,
68
103
lc -> lc_collate ,
69
- lc -> lc_monetary
70
- #ifdef LC_MESSAGES
71
- ,lc -> lc_messages
104
+ lc -> lc_monetary );
72
105
#endif
73
- );
74
106
}
75
107
76
108
#endif
@@ -109,7 +141,7 @@ PGLC_setlocale(PG_LocaleCategories * lc)
109
141
110
142
#ifdef LC_MESSAGES
111
143
if (!setlocale (LC_MESSAGES , lc -> lc_messages ))
112
- elog (NOTICE , "pg_setlocale(): 'LC_MESSAGE =%s' cannot be honored." ,
144
+ elog (NOTICE , "pg_setlocale(): 'LC_MESSAGES =%s' cannot be honored." ,
113
145
lc -> lc_messages );
114
146
#endif
115
147
}
@@ -119,24 +151,17 @@ PGLC_setlocale(PG_LocaleCategories * lc)
119
151
* with locale information for all categories. Note that returned lconv
120
152
* does not depend on currently active category settings, but on external
121
153
* environment variables for locale.
122
- *
123
- * XXX we assume that restoring old category settings via setlocale() will
124
- * not immediately corrupt the static data returned by localeconv().
125
- * How portable is this?
126
- *
127
- * XXX in any case, there certainly must not be any other calls to
128
- * localeconv() anywhere in the backend, else the values reported here
129
- * will be overwritten with the Postgres-internal locale settings.
130
154
*------
131
155
*/
132
156
struct lconv *
133
157
PGLC_localeconv (void )
134
158
{
135
159
PG_LocaleCategories lc ;
160
+ struct lconv * extlconv ;
136
161
137
162
/* Did we do it already? */
138
- if (CurrentLocaleConv )
139
- return CurrentLocaleConv ;
163
+ if (CurrentLocaleConvValid )
164
+ return & CurrentLocaleConv ;
140
165
141
166
/* Save current locale setting to lc */
142
167
PGLC_current (& lc );
@@ -145,12 +170,29 @@ PGLC_localeconv(void)
145
170
setlocale (LC_ALL , "" );
146
171
147
172
/* Get formatting information for the external environment */
148
- CurrentLocaleConv = localeconv ();
173
+ extlconv = localeconv ();
174
+
175
+ /* Must copy all values since restoring internal settings may overwrite */
176
+ CurrentLocaleConv = * extlconv ;
177
+ CurrentLocaleConv .currency_symbol = strdup (extlconv -> currency_symbol );
178
+ CurrentLocaleConv .decimal_point = strdup (extlconv -> decimal_point );
179
+ CurrentLocaleConv .grouping = strdup (extlconv -> grouping );
180
+ CurrentLocaleConv .thousands_sep = strdup (extlconv -> thousands_sep );
181
+ CurrentLocaleConv .int_curr_symbol = strdup (extlconv -> int_curr_symbol );
182
+ CurrentLocaleConv .mon_decimal_point = strdup (extlconv -> mon_decimal_point );
183
+ CurrentLocaleConv .mon_grouping = strdup (extlconv -> mon_grouping );
184
+ CurrentLocaleConv .mon_thousands_sep = strdup (extlconv -> mon_thousands_sep );
185
+ CurrentLocaleConv .negative_sign = strdup (extlconv -> negative_sign );
186
+ CurrentLocaleConv .positive_sign = strdup (extlconv -> positive_sign );
149
187
150
188
/* Restore Postgres' internal locale settings */
151
189
PGLC_setlocale (& lc );
152
190
153
- return CurrentLocaleConv ;
191
+ /* Deallocate category settings allocated in PGLC_current() */
192
+ PGLC_free_categories (& lc );
193
+
194
+ CurrentLocaleConvValid = true;
195
+ return & CurrentLocaleConv ;
154
196
}
155
197
156
198
#endif /* USE_LOCALE */
0 commit comments