1
/*-------------------------------------------------------------------------
4
* Wrapper to work around bugs in Windows setlocale() implementation
6
* Copyright (c) 2011-2013, PostgreSQL Global Development Group
9
* src/port/win32setlocale.c
12
* Windows has a problem with locale names that have a dot in the country
15
* "Chinese (Traditional)_Hong Kong S.A.R..950"
17
* For some reason, setlocale() doesn't accept that. Fortunately, Windows'
18
* setlocale() accepts various alternative names for such countries, so we
19
* provide a wrapper setlocale() function that maps the troublemaking locale
20
* names to accepted aliases.
21
*-------------------------------------------------------------------------
30
const char *locale_name_part; /* string in locale name to replace */
31
const char *replacement; /* string to replace it with */
34
static const struct locale_map locale_map_list[] = {
36
* "HKG" is listed here:
37
* http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
38
* (Country/Region Strings).
40
* "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
41
* above list, but seems to work anyway.
43
{"Hong Kong S.A.R.", "HKG"},
47
* The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
48
* seem to recognize that. And Macau isn't listed in the table of accepted
49
* abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
50
* an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
51
* where "ZHM" comes from, must be some legacy naming scheme. But hey, it
54
* Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
55
* name, not just the country part.
57
* Some versions of Windows spell it "Macau", others "Macao".
59
{"Chinese (Traditional)_Macau S.A.R..950", "ZHM"},
60
{"Chinese_Macau S.A.R..950", "ZHM"},
61
{"Chinese (Traditional)_Macao S.A.R..950", "ZHM"},
62
{"Chinese_Macao S.A.R..950", "ZHM"}
66
pgwin32_setlocale(int category, const char *locale)
73
return setlocale(category, locale);
75
/* Check if the locale name matches any of the problematic ones. */
77
for (i = 0; i < lengthof(locale_map_list); i++)
79
const char *needle = locale_map_list[i].locale_name_part;
80
const char *replacement = locale_map_list[i].replacement;
83
match = strstr(locale, needle);
86
/* Found a match. Replace the matched string. */
87
int matchpos = match - locale;
88
int replacementlen = strlen(replacement);
89
char *rest = match + strlen(needle);
90
int restlen = strlen(rest);
92
alias = malloc(matchpos + replacementlen + restlen + 1);
96
memcpy(&alias[0], &locale[0], matchpos);
97
memcpy(&alias[matchpos], replacement, replacementlen);
98
memcpy(&alias[matchpos + replacementlen], rest, restlen + 1); /* includes null
105
/* Call the real setlocale() function */
108
result = setlocale(category, alias);
112
result = setlocale(category, locale);