Make win32 builds always do SetEnvironmentVariable() when doing putenv().
authorMagnus Hagander <magnus@hagander.net>
Wed, 21 Jan 2009 10:30:02 +0000 (10:30 +0000)
committerMagnus Hagander <magnus@hagander.net>
Wed, 21 Jan 2009 10:30:02 +0000 (10:30 +0000)
Also, if linked against other versions than the default MSVCRT library
(for example the MSVC build which links against MSVCRT80), also update
the cache in the default MSVCRT at the same time.

This should fix the issues with setting LC_MESSAGES on the MSVC build.

Original patch from Hiroshi Inoue and Hiroshi Saito, much rewritten
by me.

configure
configure.in
src/backend/utils/adt/pg_locale.c
src/include/port/win32.h
src/port/win32env.c [new file with mode: 0644]
src/tools/msvc/Mkvcbuild.pm

index 38f24ffa2e22b24c266cae136183e8c8a6aa8e3a..0c25c09912bef83bb7ab9d12f387b7ba0a3ff866 100755 (executable)
--- 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"
index fadd4c53adfc3ef801d1a2414773551e9deefc71..3ece4326db6c4fcc2f6d282ca69c8ec02726b8c6 100644 (file)
@@ -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.])
index 1d35a5066274ec794afef9e35a7d6ddb5b52010d..a29673fdbf1ae8e9e00b09c47ca77b7c4f83d50c 100644 (file)
@@ -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 <shlwapi.h>
+#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 */
+
index 58baa59bffca24e1c7d13f3ba8339efcda276f77..16773c41bf4a2f54954c58f7e0caf2bf7cca101d 100644 (file)
@@ -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 (file)
index 0000000..7533549
--- /dev/null
@@ -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);
+}
+
index ae31b9fcc2b673fb3a9ed9b40748de7f9140bf74..4d70800853239552d826a309511b6b3a8b303552 100644 (file)
@@ -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');