|
4 | 4 | *
|
5 | 5 | * Portions Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
6 | 6 | *
|
7 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.32 2005/10/15 02:49:29 momjian Exp $ |
| 7 | + * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.33 2005/12/28 23:22:51 tgl Exp $ |
8 | 8 | *
|
9 | 9 | *-----------------------------------------------------------------------
|
10 | 10 | */
|
|
50 | 50 |
|
51 | 51 | #include<locale.h>
|
52 | 52 |
|
| 53 | +#include"catalog/pg_control.h" |
53 | 54 | #include"utils/pg_locale.h"
|
54 | 55 |
|
55 | 56 |
|
56 |
| -/* indicated whether locale information cache is valid */ |
57 |
| -staticboolCurrentLocaleConvValid= false; |
58 |
| - |
59 |
| - |
60 | 57 | /* GUC storage area */
|
61 | 58 |
|
62 | 59 | char*locale_messages;
|
63 | 60 | char*locale_monetary;
|
64 | 61 | char*locale_numeric;
|
65 | 62 | char*locale_time;
|
66 | 63 |
|
| 64 | +/* indicates whether locale information cache is valid */ |
| 65 | +staticboolCurrentLocaleConvValid= false; |
| 66 | + |
| 67 | +/* Environment variable storage area */ |
| 68 | + |
| 69 | +#defineLC_ENV_BUFSIZE (LOCALE_NAME_BUFLEN + 20) |
| 70 | + |
| 71 | +staticcharlc_collate_envbuf[LC_ENV_BUFSIZE]; |
| 72 | +staticcharlc_ctype_envbuf[LC_ENV_BUFSIZE]; |
| 73 | +#ifdefLC_MESSAGES |
| 74 | +staticcharlc_messages_envbuf[LC_ENV_BUFSIZE]; |
| 75 | +#endif |
| 76 | +staticcharlc_monetary_envbuf[LC_ENV_BUFSIZE]; |
| 77 | +staticcharlc_numeric_envbuf[LC_ENV_BUFSIZE]; |
| 78 | +staticcharlc_time_envbuf[LC_ENV_BUFSIZE]; |
| 79 | + |
| 80 | + |
| 81 | +/* |
| 82 | + * pg_perm_setlocale |
| 83 | + * |
| 84 | + * This is identical to the libc function setlocale(), with the addition |
| 85 | + * that if the operation is successful, the corresponding LC_XXX environment |
| 86 | + * variable is set to match. By setting the environment variable, we ensure |
| 87 | + * that any subsequent use of setlocale(..., "") will preserve the settings |
| 88 | + * made through this routine. Of course, LC_ALL must also be unset to fully |
| 89 | + * ensure that, but that has to be done elsewhere after all the individual |
| 90 | + * LC_XXX variables have been set correctly. (Thank you Perl for making this |
| 91 | + * kluge necessary.) |
| 92 | + */ |
| 93 | +char* |
| 94 | +pg_perm_setlocale(intcategory,constchar*locale) |
| 95 | +{ |
| 96 | +char*result; |
| 97 | +constchar*envvar; |
| 98 | +char*envbuf; |
| 99 | + |
| 100 | +#ifndefWIN32 |
| 101 | +result=setlocale(category,locale); |
| 102 | +#else |
| 103 | +/* |
| 104 | + * On Windows, setlocale(LC_MESSAGES) does not work, so just assume |
| 105 | + * that the given value is good and set it in the environment variables. |
| 106 | + * We must ignore attempts to set to "", which means "keep using the |
| 107 | + * old environment value". |
| 108 | + */ |
| 109 | +if (category!=LC_MESSAGES) |
| 110 | +result=setlocale(category,locale); |
| 111 | +else |
| 112 | +{ |
| 113 | +result= (char*)locale; |
| 114 | +if (locale==NULL||locale[0]=='\0') |
| 115 | +returnresult; |
| 116 | +} |
| 117 | +#endif |
| 118 | + |
| 119 | +if (result==NULL) |
| 120 | +returnresult;/* fall out immediately on failure */ |
| 121 | + |
| 122 | +switch (category) |
| 123 | +{ |
| 124 | +caseLC_COLLATE: |
| 125 | +envvar="LC_COLLATE"; |
| 126 | +envbuf=lc_collate_envbuf; |
| 127 | +break; |
| 128 | +caseLC_CTYPE: |
| 129 | +envvar="LC_CTYPE"; |
| 130 | +envbuf=lc_ctype_envbuf; |
| 131 | +break; |
| 132 | +#ifdefLC_MESSAGES |
| 133 | +caseLC_MESSAGES: |
| 134 | +envvar="LC_MESSAGES"; |
| 135 | +envbuf=lc_messages_envbuf; |
| 136 | +break; |
| 137 | +#endif |
| 138 | +caseLC_MONETARY: |
| 139 | +envvar="LC_MONETARY"; |
| 140 | +envbuf=lc_monetary_envbuf; |
| 141 | +break; |
| 142 | +caseLC_NUMERIC: |
| 143 | +envvar="LC_NUMERIC"; |
| 144 | +envbuf=lc_numeric_envbuf; |
| 145 | +break; |
| 146 | +caseLC_TIME: |
| 147 | +envvar="LC_TIME"; |
| 148 | +envbuf=lc_time_envbuf; |
| 149 | +break; |
| 150 | +default: |
| 151 | +elog(FATAL,"unrecognized LC category: %d",category); |
| 152 | +envvar=NULL;/* keep compiler quiet */ |
| 153 | +envbuf=NULL; |
| 154 | +break; |
| 155 | +} |
| 156 | + |
| 157 | +snprintf(envbuf,LC_ENV_BUFSIZE-1,"%s=%s",envvar,result); |
| 158 | + |
| 159 | +#ifndefWIN32 |
| 160 | +if (putenv(envbuf)) |
| 161 | +returnNULL; |
| 162 | +#else |
| 163 | +/* |
| 164 | + * On Windows, we need to modify both the process environment and the |
| 165 | + * cached version in msvcrt |
| 166 | + */ |
| 167 | +if (!SetEnvironmentVariable(envvar,result)) |
| 168 | +returnNULL; |
| 169 | +if (_putenv(envbuf)) |
| 170 | +returnNULL; |
| 171 | +#endif |
| 172 | + |
| 173 | +returnresult; |
| 174 | +} |
| 175 | + |
67 | 176 |
|
68 | 177 | /* GUC assign hooks */
|
69 | 178 |
|
@@ -123,48 +232,24 @@ locale_time_assign(const char *value, bool doit, GucSource source)
|
123 | 232 | constchar*
|
124 | 233 | locale_messages_assign(constchar*value,booldoit,GucSourcesource)
|
125 | 234 | {
|
126 |
| -#ifndefWIN32 |
127 |
| - |
128 | 235 | /*
|
129 | 236 | * LC_MESSAGES category does not exist everywhere, but accept it anyway
|
| 237 | + * |
| 238 | + * On Windows, we can't even check the value, so the non-doit case |
| 239 | + * is a no-op |
130 | 240 | */
|
131 | 241 | #ifdefLC_MESSAGES
|
132 | 242 | if (doit)
|
133 | 243 | {
|
134 |
| -if (!setlocale(LC_MESSAGES,value)) |
| 244 | +if (!pg_perm_setlocale(LC_MESSAGES,value)) |
135 | 245 | returnNULL;
|
136 | 246 | }
|
| 247 | +#ifndefWIN32 |
137 | 248 | else
|
138 | 249 | value=locale_xxx_assign(LC_MESSAGES,value, false,source);
|
| 250 | +#endif/* WIN32 */ |
139 | 251 | #endif/* LC_MESSAGES */
|
140 | 252 | returnvalue;
|
141 |
| -#else/* WIN32 */ |
142 |
| - |
143 |
| -/* |
144 |
| - * Win32 does not have working setlocale() for LC_MESSAGES. We can only |
145 |
| - * use environment variables to change it (per gettext FAQ). This means |
146 |
| - * we can't actually check the supplied value, so always assume it's good. |
147 |
| - * Also, ignore attempts to set to "", which really means "keep using the |
148 |
| - * old value". (Actually it means "use the environment value", but we are |
149 |
| - * too lazy to try to implement that exactly.) |
150 |
| - */ |
151 |
| -if (doit&&value[0]) |
152 |
| -{ |
153 |
| -/* |
154 |
| - * We need to modify both the process environment and the cached |
155 |
| - * version in msvcrt |
156 |
| - */ |
157 |
| -staticcharenv[128]; |
158 |
| - |
159 |
| -if (!SetEnvironmentVariable("LC_MESSAGES",value)) |
160 |
| -returnNULL; |
161 |
| - |
162 |
| -snprintf(env,sizeof(env)-1,"LC_MESSAGES=%s",value); |
163 |
| -if (_putenv(env)) |
164 |
| -returnNULL; |
165 |
| -} |
166 |
| -returnvalue; |
167 |
| -#endif/* WIN32 */ |
168 | 253 | }
|
169 | 254 |
|
170 | 255 |
|
|