]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/pg_locale.c
Locale support is on by default. The choice of locale is done in initdb
[postgresql] / src / backend / utils / adt / pg_locale.c
1 /*-----------------------------------------------------------------------
2  *
3  * PostgreSQL locale utilities
4  *
5  * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.16 2002/04/03 05:39:31 petere Exp $
6  *
7  * Portions Copyright (c) 2002, PostgreSQL Global Development Group
8  *
9  *-----------------------------------------------------------------------
10  */
11
12 #include "postgres.h"
13 #include "utils/pg_locale.h"
14 #include <locale.h>
15
16
17 /* GUC storage area */
18
19 char * locale_messages;
20 char * locale_monetary;
21 char * locale_numeric;
22 char * locale_time;
23
24 /* GUC parse hooks */
25
26 bool locale_messages_check(const char *proposed)
27 {
28 #ifdef LC_MESSAGES
29         return chklocale(LC_MESSAGES, proposed);
30 #else
31         /* We return true here so LC_MESSAGES can be set in the
32        configuration file on every system. */
33         return true;
34 #endif
35 }
36
37 bool locale_monetary_check(const char *proposed)
38 {
39         return chklocale(LC_MONETARY, proposed);
40 }
41
42 bool locale_numeric_check(const char *proposed)
43 {
44         return chklocale(LC_NUMERIC, proposed);
45 }
46
47 bool locale_time_check(const char *proposed)
48 {
49         return chklocale(LC_TIME, proposed);
50 }
51
52 /* GUC assign hooks */
53
54 void locale_messages_assign(const char *value)
55 {
56 #ifdef LC_MESSAGES
57         setlocale(LC_MESSAGES, value);
58 #endif
59 }
60
61 void locale_monetary_assign(const char *value)
62 {
63         setlocale(LC_MONETARY, value);
64 }
65
66 void locale_numeric_assign(const char *value)
67 {
68         setlocale(LC_NUMERIC, value);
69 }
70
71 void locale_time_assign(const char *value)
72 {
73         setlocale(LC_TIME, value);
74 }
75
76
77 /*
78  * Returns true if the proposed string represents a valid locale of
79  * the given category.  This is probably pretty slow, but it's not
80  * called in critical places.
81  */
82 bool
83 chklocale(int category, const char *proposed)
84 {
85         char *save;
86
87         save = setlocale(category, NULL);
88         if (!save)
89                 return false;
90
91         if (!setlocale(category, proposed))
92                 return false;
93
94         setlocale(category, save);
95         return true;
96 }
97
98
99 /*
100  * We'd like to cache whether LC_COLLATE is C (or POSIX), so we can
101  * optimize a few code paths in various places.
102  */
103 bool
104 lc_collate_is_c(void)
105 {
106         /* Cache result so we only have to compute it once */
107         static int      result = -1;
108         char       *localeptr;
109
110         if (result >= 0)
111                 return (bool) result;
112         localeptr = setlocale(LC_COLLATE, NULL);
113         if (!localeptr)
114                 elog(PANIC, "Invalid LC_COLLATE setting");
115
116         if (strcmp(localeptr, "C") == 0)
117                 result = true;
118         else if (strcmp(localeptr, "POSIX") == 0)
119                 result = true;
120         else
121                 result = false;
122         return (bool) result;
123 }
124
125
126
127 /*
128  * Return the POSIX lconv struct (contains number/money formatting
129  * information) with locale information for all categories.
130  */
131 struct lconv *
132 PGLC_localeconv(void)
133 {
134         struct lconv *extlconv;
135         static bool CurrentLocaleConvValid = false;
136         static struct lconv CurrentLocaleConv;
137
138         /* Did we do it already? */
139         if (CurrentLocaleConvValid)
140                 return &CurrentLocaleConv;
141
142         /* Get formatting information for the external environment */
143         extlconv = localeconv();
144
145         /*
146          * Must copy all values since restoring internal settings may
147          * overwrite
148          */
149         CurrentLocaleConv = *extlconv;
150         CurrentLocaleConv.currency_symbol = strdup(extlconv->currency_symbol);
151         CurrentLocaleConv.decimal_point = strdup(extlconv->decimal_point);
152         CurrentLocaleConv.grouping = strdup(extlconv->grouping);
153         CurrentLocaleConv.thousands_sep = strdup(extlconv->thousands_sep);
154         CurrentLocaleConv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
155         CurrentLocaleConv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
156         CurrentLocaleConv.mon_grouping = strdup(extlconv->mon_grouping);
157         CurrentLocaleConv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
158         CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
159         CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
160
161         CurrentLocaleConvValid = true;
162         return &CurrentLocaleConv;
163 }