44 * The PostgreSQL locale utils.
55 *
66 *
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 $
88 *
99 * Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
1010 *
11- * Karel Zak - Zakkr
11+ * Karel Zak
1212 *
1313 * -----------------------------------------------------------------------
1414 */
1818#ifdef USE_LOCALE
1919
2020#include <locale.h>
21+
2122#include "utils/pg_locale.h"
2223
2324/* #define DEBUG_LOCALE_UTILS */
2425
2526
26- static struct lconv * CurrentLocaleConv = NULL ;
27+ static bool CurrentLocaleConvValid = false;
28+ static struct lconv CurrentLocaleConv ;
29+
2730
2831static void PGLC_setlocale (PG_LocaleCategories * lc );
2932
3033/*------
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!
3261 *------
3362 */
3463void
3564PGLC_current (PG_LocaleCategories * lc )
3665{
3766lc -> lang = getenv ("LANG" );
3867
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 ) );
4473#ifdef LC_MESSAGES
45- lc -> lc_messages = setlocale (LC_MESSAGES ,NULL );
74+ lc -> lc_messages = pstrdup ( setlocale (LC_MESSAGES ,NULL ) );
4675#endif
4776}
4877
@@ -58,19 +87,22 @@ PGLC_debug_lc(PG_LocaleCategories * lc)
5887{
5988#ifdef LC_MESSAGES
6089elog (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 );
6197#else
6298elog (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
6499lc -> lang ,
65100lc -> lc_ctype ,
66101lc -> lc_numeric ,
67102lc -> lc_time ,
68103lc -> lc_collate ,
69- lc -> lc_monetary
70- #ifdef LC_MESSAGES
71- ,lc -> lc_messages
104+ lc -> lc_monetary );
72105#endif
73- );
74106}
75107
76108#endif
@@ -109,7 +141,7 @@ PGLC_setlocale(PG_LocaleCategories * lc)
109141
110142#ifdef LC_MESSAGES
111143if (!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." ,
113145lc -> lc_messages );
114146#endif
115147}
@@ -119,24 +151,17 @@ PGLC_setlocale(PG_LocaleCategories * lc)
119151 * with locale information for all categories.Note that returned lconv
120152 * does not depend on currently active category settings, but on external
121153 * 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.
130154 *------
131155 */
132156struct lconv *
133157PGLC_localeconv (void )
134158{
135159PG_LocaleCategories lc ;
160+ struct lconv * extlconv ;
136161
137162/* Did we do it already? */
138- if (CurrentLocaleConv )
139- return CurrentLocaleConv ;
163+ if (CurrentLocaleConvValid )
164+ return & CurrentLocaleConv ;
140165
141166/* Save current locale setting to lc */
142167PGLC_current (& lc );
@@ -145,12 +170,29 @@ PGLC_localeconv(void)
145170setlocale (LC_ALL ,"" );
146171
147172/* 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 );
149187
150188/* Restore Postgres' internal locale settings */
151189PGLC_setlocale (& lc );
152190
153- return CurrentLocaleConv ;
191+ /* Deallocate category settings allocated in PGLC_current() */
192+ PGLC_free_categories (& lc );
193+
194+ CurrentLocaleConvValid = true;
195+ return & CurrentLocaleConv ;
154196}
155197
156198#endif /* USE_LOCALE */