diff --git a/configure b/configure index 38f24ffa2e..0c25c09912 100755 --- a/configure +++ b/configure @@ -17919,6 +17919,12 @@ case " $LIBOBJS " in ;; esac +case " $LIBOBJS " in + *" win32env.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS win32env.$ac_objext" + ;; +esac + case " $LIBOBJS " in *" win32error.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS win32error.$ac_objext" diff --git a/configure.in b/configure.in index fadd4c53ad..3ece4326db 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl $PostgreSQL: pgsql/configure.in,v 1.587 2009/01/14 18:10:21 momjian Exp $ +dnl $PostgreSQL: pgsql/configure.in,v 1.588 2009/01/21 10:30:02 mha Exp $ dnl dnl Developers, please strive to achieve this order: dnl @@ -1274,6 +1274,7 @@ AC_REPLACE_FUNCS(gettimeofday) AC_LIBOBJ(kill) AC_LIBOBJ(open) AC_LIBOBJ(rand) +AC_LIBOBJ(win32env) AC_LIBOBJ(win32error) AC_DEFINE([HAVE_SYMLINK], 1, [Define to 1 if you have the `symlink' function.]) diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 1d35a50662..a29673fdbf 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -4,7 +4,7 @@ * * Portions Copyright (c) 2002-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.45 2009/01/09 14:07:00 mha Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.46 2009/01/21 10:30:02 mha Exp $ * *----------------------------------------------------------------------- */ @@ -55,6 +55,9 @@ #include "utils/memutils.h" #include "utils/pg_locale.h" +#ifdef WIN32 +#include +#endif #define MAX_L10N_DATA 80 @@ -89,6 +92,10 @@ static char lc_monetary_envbuf[LC_ENV_BUFSIZE]; static char lc_numeric_envbuf[LC_ENV_BUFSIZE]; static char lc_time_envbuf[LC_ENV_BUFSIZE]; +#ifdef WIN32 +static char *IsoLocaleName(const char *); /* MSVC specific */ +#endif + /* * pg_perm_setlocale @@ -148,8 +155,13 @@ pg_perm_setlocale(int category, const char *locale) case LC_MESSAGES: envvar = "LC_MESSAGES"; envbuf = lc_messages_envbuf; +#ifdef WIN32 + result = IsoLocaleName(locale); + if (result == NULL) + result = locale; +#endif /* WIN32 */ break; -#endif +#endif /* LC_MESSAGES */ case LC_MONETARY: envvar = "LC_MONETARY"; envbuf = lc_monetary_envbuf; @@ -166,25 +178,13 @@ pg_perm_setlocale(int category, const char *locale) elog(FATAL, "unrecognized LC category: %d", category); envvar = NULL; /* keep compiler quiet */ envbuf = NULL; - break; + return NULL; } snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result); -#ifndef WIN32 if (putenv(envbuf)) return NULL; -#else - - /* - * On Windows, we need to modify both the process environment and the - * cached version in msvcrt - */ - if (!SetEnvironmentVariable(envvar, result)) - return NULL; - if (_putenv(envbuf)) - return NULL; -#endif return result; } @@ -599,3 +599,53 @@ cache_locale_time(void) CurrentLCTimeValid = true; } + + +#ifdef WIN32 +/* + * Convert Windows locale name to the ISO formatted one + * if possible. + * + * This function returns NULL if conversion is impossible, + * otherwise returns the pointer to a static area which + * contains the iso formatted locale name. + */ +static +char *IsoLocaleName(const char *winlocname) +{ +#if (_MSC_VER >= 1400) /* VC8.0 or later */ + static char iso_lc_messages[32]; + _locale_t loct = NULL; + + if (pg_strcasecmp("c", winlocname) == 0 || + pg_strcasecmp("posix", winlocname) == 0) + { + strcpy(iso_lc_messages, "C"); + return iso_lc_messages; + } + + loct = _create_locale(LC_CTYPE, winlocname); + if (loct != NULL) + { + char isolang[32], isocrty[32]; + LCID lcid; + + lcid = loct->locinfo->lc_handle[LC_CTYPE]; + if (lcid == 0) + lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + _free_locale(loct); + + if (!GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, isolang, sizeof(isolang))) + return NULL; + if (!GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty, sizeof(isocrty)))' + return NULL; + snprintf(iso_lc_messages, sizeof(iso_lc_messages) - 1, "%s_%s", isolang, isocrty); + return iso_lc_messages; + } + return NULL; +#else + return NULL; /* Not supported on this version of msvc/mingw */ +#endif /* _MSC_VER >= 1400 */ +} +#endif /* WIN32 */ + diff --git a/src/include/port/win32.h b/src/include/port/win32.h index 58baa59bff..16773c41bf 100644 --- a/src/include/port/win32.h +++ b/src/include/port/win32.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.85 2009/01/07 03:39:33 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.86 2009/01/21 10:30:02 mha Exp $ */ #if defined(_MSC_VER) || defined(__BORLANDC__) #define WIN32_ONLY_COMPILER @@ -291,6 +291,11 @@ extern int pgwin32_is_service(void); /* in port/win32error.c */ extern void _dosmaperr(unsigned long); +/* in port/win32env.c */ +extern int pgwin32_putenv(const char *); +extern void pgwin32_unsetenv(const char *); +#define putenv(x) pgwin32_putenv(x) +#define unsetenv(x) pgwin32_unsetenv(x) /* Things that exist in MingW headers, but need to be added to MSVC */ #ifdef WIN32_ONLY_COMPILER diff --git a/src/port/win32env.c b/src/port/win32env.c new file mode 100644 index 0000000000..7533549608 --- /dev/null +++ b/src/port/win32env.c @@ -0,0 +1,93 @@ +/*------------------------------------------------------------------------- + * + * win32env.c + * putenv() and unsetenv() for win32, that updates both process + * environment and the cached versions in (potentially multiple) + * MSVCRT. + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/port/win32env.c,v 1.1 2009/01/21 10:30:02 mha Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "c.h" + +int +pgwin32_putenv(const char *envval) +{ + char *envcpy; + char *cp; + + /* + * Each version of MSVCRT has its own _putenv() call in the runtime + * library. + * + * If we're in VC 7.0 or later (means != mingw), update in + * the 6.0 MSVCRT.DLL environment as well, to work with third party + * libraries linked against it (such as gnuwin32 libraries). + */ +#if defined(_MSC_VER) && (_MSC_VER >= 1300) + typedef int (_cdecl *PUTENVPROC)(const char *); + HMODULE hmodule; + static PUTENVPROC putenvFunc = NULL; + int ret; + + if (putenvFunc == NULL) + { + hmodule = GetModuleHandle("msvcrt"); + if (hmodule == NULL) + return 1; + putenvFunc = (PUTENVPROC)GetProcAddress(hmodule, "_putenv"); + if (putenvFunc == NULL) + return 1; + } + ret = putenvFunc(envval); + if (ret != 0) + return ret; +#endif /* _MSC_VER >= 1300 */ + + + /* + * Update the process environment - to make modifications visible + * to child processes. + * + * Need a copy of the string so we can modify it. + */ + envcpy = strdup(envval); + cp = strchr(envcpy, '='); + if (cp == NULL) + return -1; + *cp = '\0'; + cp++; + if (strlen(cp) == 0) + cp = NULL; + if (!SetEnvironmentVariable(envcpy, cp)) + { + free(envcpy); + return -1; + } + free(envcpy); + + /* Finally, update our "own" cache */ + return _putenv(envval); +} + +void +pgwin32_unsetenv(const char *name) +{ + char *envbuf; + + envbuf = (char *) malloc(strlen(name)+2); + if (!envbuf) + return; + + sprintf(envbuf, "%s=", name); + pgwin32_putenv(envbuf); + free(envbuf); +} + diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index ae31b9fcc2..4d70800853 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -3,7 +3,7 @@ package Mkvcbuild; # # Package that generates build files for msvc build # -# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.35 2008/12/20 22:04:02 mha Exp $ +# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.36 2009/01/21 10:30:02 mha Exp $ # use Carp; use Win32; @@ -44,10 +44,10 @@ sub mkvcbuild our @pgportfiles = qw( chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c - unsetenv.c getaddrinfo.c gettimeofday.c kill.c open.c rand.c + getaddrinfo.c gettimeofday.c kill.c open.c rand.c snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c - getopt.c getopt_long.c dirent.c rint.c win32error.c); + getopt.c getopt_long.c dirent.c rint.c win32env.c win32error.c); $libpgport = $solution->AddProject('libpgport','lib','misc'); $libpgport->AddDefine('FRONTEND');