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);