mirror of
https://github.com/postgres/postgres.git
synced 2025-08-19 23:22:23 +03:00
Fix MinGW build, broken by my previous patch to add a setlocale() wrapper
on Windows. ecpglib doesn't link with libpgport, but picks and compiles the .c files it needs individually. To cope with that, move the setlocale() wrapper from chklocale.c to a separate setlocale.c file, and include that in ecpglib.
This commit is contained in:
115
src/port/win32setlocale.c
Normal file
115
src/port/win32setlocale.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* win32setlocale.c
|
||||
* Wrapper to work around bugs in Windows setlocale() implementation
|
||||
*
|
||||
* Copyright (c) 2011, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/port/win32setlocale.c
|
||||
*
|
||||
*
|
||||
* Windows has a problem with locale names that have a dot in the country
|
||||
* name. For example:
|
||||
*
|
||||
* "Chinese (Traditional)_Hong Kong S.A.R..950"
|
||||
*
|
||||
* For some reason, setlocale() doesn't accept that. Fortunately, Windows'
|
||||
* setlocale() accepts various alternative names for such countries, so we
|
||||
* provide a wrapper setlocale() function that maps the troublemaking locale
|
||||
* names to accepted aliases.
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "c.h"
|
||||
|
||||
#undef setlocale
|
||||
|
||||
struct locale_map
|
||||
{
|
||||
const char *locale_name_part; /* string in locale name to replace */
|
||||
const char *replacement; /* string to replace it with */
|
||||
};
|
||||
|
||||
static const struct locale_map locale_map_list[] = {
|
||||
|
||||
/*
|
||||
* "HKG" is listed here:
|
||||
* http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
|
||||
* (Country/Region Strings).
|
||||
*
|
||||
* "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
|
||||
* above list, but seems to work anyway.
|
||||
*/
|
||||
{ "Hong Kong S.A.R.", "HKG" },
|
||||
{ "U.A.E.", "ARE" },
|
||||
|
||||
/*
|
||||
* The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
|
||||
* seem to recognize that. And Macau isn't listed in the table of
|
||||
* accepted abbreviations linked above. Fortunately, "ZHM" seems to be
|
||||
* accepted as an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm
|
||||
* not sure where "ZHM" comes from, must be some legacy naming scheme. But
|
||||
* hey, it works.
|
||||
*
|
||||
* Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
|
||||
* name, not just the country part.
|
||||
*
|
||||
* Some versions of Windows spell it "Macau", others "Macao".
|
||||
*/
|
||||
{ "Chinese (Traditional)_Macau S.A.R..950", "ZHM" },
|
||||
{ "Chinese_Macau S.A.R..950", "ZHM" },
|
||||
{ "Chinese (Traditional)_Macao S.A.R..950", "ZHM" },
|
||||
{ "Chinese_Macao S.A.R..950", "ZHM" }
|
||||
};
|
||||
|
||||
char *
|
||||
pgwin32_setlocale(int category, const char *locale)
|
||||
{
|
||||
char *result;
|
||||
char *alias;
|
||||
int i;
|
||||
|
||||
if (locale == NULL)
|
||||
return setlocale(category, locale);
|
||||
|
||||
/* Check if the locale name matches any of the problematic ones. */
|
||||
alias = NULL;
|
||||
for (i = 0; i < lengthof(locale_map_list); i++)
|
||||
{
|
||||
const char *needle = locale_map_list[i].locale_name_part;
|
||||
const char *replacement = locale_map_list[i].replacement;
|
||||
char *match;
|
||||
|
||||
match = strstr(locale, needle);
|
||||
if (match != NULL)
|
||||
{
|
||||
/* Found a match. Replace the matched string. */
|
||||
int matchpos = match - locale;
|
||||
int replacementlen = strlen(replacement);
|
||||
char *rest = match + strlen(needle);
|
||||
int restlen = strlen(rest);
|
||||
|
||||
alias = malloc(matchpos + replacementlen + restlen + 1);
|
||||
if (!alias)
|
||||
return NULL;
|
||||
|
||||
memcpy(&alias[0], &locale[0], matchpos);
|
||||
memcpy(&alias[matchpos], replacement, replacementlen);
|
||||
memcpy(&alias[matchpos + replacementlen], rest, restlen + 1); /* includes null terminator */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the real setlocale() function */
|
||||
if (alias)
|
||||
{
|
||||
result = setlocale(category, alias);
|
||||
free(alias);
|
||||
}
|
||||
else
|
||||
result = setlocale(category, locale);
|
||||
|
||||
return result;
|
||||
}
|
Reference in New Issue
Block a user