aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/adt/pg_locale.c98
-rw-r--r--src/include/utils/pg_locale.h10
2 files changed, 78 insertions, 30 deletions
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index faa81cd09af..513328d35c5 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -4,11 +4,11 @@
* The PostgreSQL locale utils.
*
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.9 2001/03/22 03:59:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.10 2001/09/29 21:16:30 tgl Exp $
*
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
*
- * Karel Zak - Zakkr
+ * Karel Zak
*
* -----------------------------------------------------------------------
*/
@@ -18,17 +18,46 @@
#ifdef USE_LOCALE
#include <locale.h>
+
#include "utils/pg_locale.h"
/* #define DEBUG_LOCALE_UTILS */
-static struct lconv *CurrentLocaleConv = NULL;
+static bool CurrentLocaleConvValid = false;
+static struct lconv CurrentLocaleConv;
+
static void PGLC_setlocale(PG_LocaleCategories * lc);
/*------
- * Return in PG_LocaleCategories the current locale settings
+ * Frees memory used in PG_LocaleCategories -- this memory is
+ * allocated in PGLC_current().
+ *------
+ */
+void
+PGLC_free_categories(PG_LocaleCategories * lc)
+{
+ if (lc->lc_ctype)
+ pfree(lc->lc_ctype);
+ if (lc->lc_numeric)
+ pfree(lc->lc_numeric);
+ if (lc->lc_time)
+ pfree(lc->lc_time);
+ if (lc->lc_collate)
+ pfree(lc->lc_collate);
+ if (lc->lc_monetary);
+ pfree(lc->lc_monetary);
+#ifdef LC_MESSAGES
+ if (lc->lc_messages)
+ pfree(lc->lc_messages);
+#endif
+}
+
+/*------
+ * Return in PG_LocaleCategories the current locale settings.
+ *
+ * NB: strings are allocated in the current memory context!
*------
*/
void
@@ -36,13 +65,13 @@ PGLC_current(PG_LocaleCategories * lc)
{
lc->lang = getenv("LANG");
- lc->lc_ctype = setlocale(LC_CTYPE, NULL);
- lc->lc_numeric = setlocale(LC_NUMERIC, NULL);
- lc->lc_time = setlocale(LC_TIME, NULL);
- lc->lc_collate = setlocale(LC_COLLATE, NULL);
- lc->lc_monetary = setlocale(LC_MONETARY, NULL);
+ lc->lc_ctype = pstrdup( setlocale(LC_CTYPE, NULL) );
+ lc->lc_numeric = pstrdup( setlocale(LC_NUMERIC, NULL) );
+ lc->lc_time = pstrdup( setlocale(LC_TIME, NULL) );
+ lc->lc_collate = pstrdup( setlocale(LC_COLLATE, NULL) );
+ lc->lc_monetary = pstrdup( setlocale(LC_MONETARY, NULL) );
#ifdef LC_MESSAGES
- lc->lc_messages = setlocale(LC_MESSAGES, NULL);
+ lc->lc_messages = pstrdup( setlocale(LC_MESSAGES, NULL) );
#endif
}
@@ -58,19 +87,22 @@ PGLC_debug_lc(PG_LocaleCategories * lc)
{
#ifdef LC_MESSAGES
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",
+ lc->lang,
+ lc->lc_ctype,
+ lc->lc_numeric,
+ lc->lc_time,
+ lc->lc_collate,
+ lc->lc_monetary,
+ lc->lc_messages);
#else
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",
-#endif
lc->lang,
lc->lc_ctype,
lc->lc_numeric,
lc->lc_time,
lc->lc_collate,
- lc->lc_monetary
-#ifdef LC_MESSAGES
- ,lc->lc_messages
+ lc->lc_monetary);
#endif
- );
}
#endif
@@ -109,7 +141,7 @@ PGLC_setlocale(PG_LocaleCategories * lc)
#ifdef LC_MESSAGES
if (!setlocale(LC_MESSAGES, lc->lc_messages))
- elog(NOTICE, "pg_setlocale(): 'LC_MESSAGE=%s' cannot be honored.",
+ elog(NOTICE, "pg_setlocale(): 'LC_MESSAGES=%s' cannot be honored.",
lc->lc_messages);
#endif
}
@@ -119,24 +151,17 @@ PGLC_setlocale(PG_LocaleCategories * lc)
* with locale information for all categories. Note that returned lconv
* does not depend on currently active category settings, but on external
* environment variables for locale.
- *
- * XXX we assume that restoring old category settings via setlocale() will
- * not immediately corrupt the static data returned by localeconv().
- * How portable is this?
- *
- * XXX in any case, there certainly must not be any other calls to
- * localeconv() anywhere in the backend, else the values reported here
- * will be overwritten with the Postgres-internal locale settings.
*------
*/
struct lconv *
PGLC_localeconv(void)
{
PG_LocaleCategories lc;
+ struct lconv *extlconv;
/* Did we do it already? */
- if (CurrentLocaleConv)
- return CurrentLocaleConv;
+ if (CurrentLocaleConvValid)
+ return &CurrentLocaleConv;
/* Save current locale setting to lc */
PGLC_current(&lc);
@@ -145,12 +170,29 @@ PGLC_localeconv(void)
setlocale(LC_ALL, "");
/* Get formatting information for the external environment */
- CurrentLocaleConv = localeconv();
+ extlconv = localeconv();
+
+ /* Must copy all values since restoring internal settings may overwrite */
+ CurrentLocaleConv = *extlconv;
+ CurrentLocaleConv.currency_symbol = strdup(extlconv->currency_symbol);
+ CurrentLocaleConv.decimal_point = strdup(extlconv->decimal_point);
+ CurrentLocaleConv.grouping = strdup(extlconv->grouping);
+ CurrentLocaleConv.thousands_sep = strdup(extlconv->thousands_sep);
+ CurrentLocaleConv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
+ CurrentLocaleConv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
+ CurrentLocaleConv.mon_grouping = strdup(extlconv->mon_grouping);
+ CurrentLocaleConv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
+ CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
+ CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
/* Restore Postgres' internal locale settings */
PGLC_setlocale(&lc);
- return CurrentLocaleConv;
+ /* Deallocate category settings allocated in PGLC_current() */
+ PGLC_free_categories(&lc);
+
+ CurrentLocaleConvValid = true;
+ return &CurrentLocaleConv;
}
#endif /* USE_LOCALE */
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 062806bc398..d6257b7654e 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -4,7 +4,7 @@
* The PostgreSQL locale utils.
*
*
- * $Id: pg_locale.h,v 1.7 2001/03/22 04:01:14 momjian Exp $
+ * $Id: pg_locale.h,v 1.8 2001/09/29 21:16:30 tgl Exp $
*
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
*
@@ -33,8 +33,14 @@ typedef struct PG_LocaleCategories
*lc_messages;
} PG_LocaleCategories;
-
+/*
+ * Save locale category settings into PG memory
+ */
extern void PGLC_current(PG_LocaleCategories * lc);
+/*
+ * Free memory allocated in PGLC_current()
+ */
+extern void PGLC_free_categories(PG_LocaleCategories * lc);
/*------
* Return the POSIX lconv struct (contains number/money formatting information)