Re: [BUGS] BUG #4186: set lc_messages does not work - Mailing list pgsql-hackers

From Hiroshi Inoue
Subject Re: [BUGS] BUG #4186: set lc_messages does not work
Date
Msg-id 49665481.7060902@tpf.co.jp
Whole thread Raw
In response to Re: [BUGS] BUG #4186: set lc_messages does not work  (Hiroshi Inoue <inoue@tpf.co.jp>)
Responses Re: [BUGS] BUG #4186: set lc_messages does not work  (Magnus Hagander <magnus@hagander.net>)
List pgsql-hackers
Hiroshi Inoue wrote:
> Magnus Hagander wrote:
>>
>> Do you want to send an updated patch for it, or do you want me to look
>> at it?
>
> I would send a new patch to which I added a simple ISO style check for
>  locale names.

Attached is a new patch.
I added a simple ISO style locale name check.
Avoided codings like *NULL == somthing*.
It also includes the changes to mbutils.c and elog.c which fix
recently introduced bug by the domain name change from "postgres"
to "postgres-8.4".

regards,
Hiroshi Inoue


Index: backend/utils/adt/pg_locale.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v
retrieving revision 1.43
diff -c -c -r1.43 pg_locale.c
*** backend/utils/adt/pg_locale.c    1 Jan 2009 17:23:49 -0000    1.43
--- backend/utils/adt/pg_locale.c    8 Jan 2009 19:26:02 -0000
***************
*** 88,93 ****
--- 88,102 ----
  static char lc_numeric_envbuf[LC_ENV_BUFSIZE];
  static char lc_time_envbuf[LC_ENV_BUFSIZE];

+ /*
+  *    The following 2 functions are ajusted ones for Windows MSVC.
+  */
+ static int pg_putenv(const char *);    /* putenv() adjusted for MSVC */
+ extern void pg_unsetenv(const char *);    /* unsetenv() adjusted for MSVC */
+ /*    The following function is available under MSVC8.0 or later */
+ #ifdef WIN32
+ static char *IsoLocaleName(const char *); /* MSVC specific */
+ #endif

  /*
   * pg_perm_setlocale
***************
*** 147,152 ****
--- 156,167 ----
          case LC_MESSAGES:
              envvar = "LC_MESSAGES";
              envbuf = lc_messages_envbuf;
+             /* Refresh msgid pool maintained by gettext? */
+             // textdomain(textdomain(NULL));
+ #ifdef WIN32
+             if (result = IsoLocaleName(locale), result == NULL)
+                 return NULL;
+ #endif /* WIN32 */
              break;
  #endif
          case LC_MONETARY:
***************
*** 165,171 ****
              elog(FATAL, "unrecognized LC category: %d", category);
              envvar = NULL;        /* keep compiler quiet */
              envbuf = NULL;
!             break;
      }

      snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
--- 180,186 ----
              elog(FATAL, "unrecognized LC category: %d", category);
              envvar = NULL;        /* keep compiler quiet */
              envbuf = NULL;
!             return NULL;
      }

      snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
***************
*** 181,189 ****
       */
      if (!SetEnvironmentVariable(envvar, result))
          return NULL;
!     if (_putenv(envbuf))
!         return NULL;
! #endif

      return result;
  }
--- 196,204 ----
       */
      if (!SetEnvironmentVariable(envvar, result))
          return NULL;
!     if (pg_putenv(envbuf))
!         result = NULL;
! #endif /* WIN32 */

      return result;
  }
***************
*** 214,219 ****
--- 229,352 ----
      return ret;
  }

+ /*
+  *    Ajusted version of putenv() for MSVC.
+  */
+ static
+ int pg_putenv(const char *envval)
+ {
+ #if defined(_MSC_VER) && (_MSC_VER >= 1300) /* VC7.0 or later */
+ /*
+  *    Each MSVC version has its own _putenv() in its runtime library
+  *    msvcrXX.dll. So we have to call _putenv() in msvcrt.dll so as
+  *    to be referenced by GnuWin32 library.
+  */
+     typedef int (_cdecl *PUTENVPROC)(const char *);
+     HMODULE    hmodule;
+     static PUTENVPROC    putenvFunc = NULL;
+     int    ret;
+
+     if (putenvFunc == NULL)
+     {
+         if (hmodule = GetModuleHandle("msvcrt"), hmodule == NULL)
+             return 1;
+         putenvFunc = (PUTENVPROC) GetProcAddress(hmodule, "_putenv");
+         if (putenvFunc == NULL)
+             return 1;
+     }
+     if (ret = putenvFunc(envval), ret != 0)
+         return ret;
+ #endif /* _MSC_VER >= 1300 */
+     return putenv(envval);
+ }
+
+ /*
+  *    Adjusted version of unsetenv() for MSVC.
+  */
+ void pg_unsetenv(const char *name)
+ {
+ #ifdef    WIN32
+     char *envbuf;
+
+     if (envbuf = (char *) malloc(strlen(name) + 2))
+     {
+         sprintf(envbuf, "%s=", name);
+         pg_putenv(envbuf);
+         free(envbuf);
+     }
+ #else
+     unsetenv(name);
+ #endif /* WIN32 */
+ }
+
+ #ifdef WIN32
+ /*
+  *    Convert Windows locale name to the ISO's one if possible.
+  *
+  *    This function returns NULL if conversion is impossible
+  *    and the format style isn't ISO, otherwise returns 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];
+     int        usecategory = LC_CTYPE;
+     _locale_t    loct = NULL;
+
+     if (stricmp("c", winlocname) == 0 ||
+         stricmp("posix", winlocname) == 0)
+     {
+         strncpy(iso_lc_messages, "C", sizeof(iso_lc_messages));
+         return iso_lc_messages;
+     }
+
+     loct = _create_locale(usecategory, winlocname);
+     if (loct != NULL)
+     {
+         char    isolang[32], isocrty[32];
+         LCID    lcid;
+
+         lcid = loct->locinfo->lc_handle[usecategory];
+         if (lcid == 0)
+             lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+         _free_locale(loct);
+
+
+         GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, isolang, sizeof(isolang));
+         GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty, sizeof(isocrty));
+         snprintf(iso_lc_messages, sizeof(iso_lc_messages) - 1, "%s_%s", isolang, isocrty);
+         return iso_lc_messages;
+     }
+     else    /* ISO style check */
+     {
+         int    lclen;
+         char    *dotp;
+
+         if (dotp = strchr(winlocname, '.'), dotp != NULL)
+             lclen = dotp - winlocname;
+         else
+             lclen = strlen(winlocname);
+         switch (lclen)
+         {
+             case 2:
+                 break;
+             case 5:
+                 if (winlocname[2] != '_')
+                     return NULL;
+                 break;
+             default:
+                 return NULL;
+         }
+     }
+     return winlocname;
+ #else
+     return winlocname; /* does nothing. */
+ #endif /* _MSC_VER >= 1400 */
+ }
+ #endif /* WIN32 */
+
  /* GUC assign hooks */

  /*
Index: backend/main/main.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/main/main.c,v
retrieving revision 1.112
diff -c -c -r1.112 main.c
*** backend/main/main.c    1 Jan 2009 17:23:43 -0000    1.112
--- backend/main/main.c    8 Jan 2009 19:26:03 -0000
***************
*** 132,138 ****
       * environment, remove any LC_ALL setting, so that the environment
       * variables installed by pg_perm_setlocale have force.
       */
!     unsetenv("LC_ALL");

      /*
       * Catch standard options before doing much else
--- 132,138 ----
       * environment, remove any LC_ALL setting, so that the environment
       * variables installed by pg_perm_setlocale have force.
       */
!     pg_unsetenv("LC_ALL");

      /*
       * Catch standard options before doing much else
Index: include/utils/pg_locale.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/pg_locale.h,v
retrieving revision 1.27
diff -c -c -r1.27 pg_locale.h
*** include/utils/pg_locale.h    1 Jan 2009 17:24:02 -0000    1.27
--- include/utils/pg_locale.h    8 Jan 2009 19:26:03 -0000
***************
*** 53,56 ****
--- 53,58 ----

  extern void cache_locale_time(void);

+ extern void pg_unsetenv(const char *);
+
  #endif   /* _PG_LOCALE_ */
Index: backend/utils/mb/mbutils.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v
retrieving revision 1.76
diff -c -c -r1.76 mbutils.c
*** backend/utils/mb/mbutils.c    4 Jan 2009 18:37:35 -0000    1.76
--- backend/utils/mb/mbutils.c    8 Jan 2009 19:26:03 -0000
***************
*** 873,879 ****
       */
  #ifdef ENABLE_NLS
      if (encoding == PG_UTF8)
!         if (bind_textdomain_codeset("postgres", "UTF-8") == NULL)
              elog(LOG, "bind_textdomain_codeset failed");
  #endif
  }
--- 873,879 ----
       */
  #ifdef ENABLE_NLS
      if (encoding == PG_UTF8)
!         if (bind_textdomain_codeset(textdomain(NULL), "UTF-8") == NULL)
              elog(LOG, "bind_textdomain_codeset failed");
  #endif
  }
Index: backend/utils/error/elog.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/error/elog.c,v
retrieving revision 1.211
diff -c -c -r1.211 elog.c
*** backend/utils/error/elog.c    7 Jan 2009 04:26:46 -0000    1.211
--- backend/utils/error/elog.c    8 Jan 2009 19:26:05 -0000
***************
*** 308,314 ****
      edata->lineno = lineno;
      edata->funcname = funcname;
      /* the default text domain is the backend's */
!     edata->domain = domain ? domain : "postgres";
      /* Select default errcode based on elevel */
      if (elevel >= ERROR)
          edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
--- 308,314 ----
      edata->lineno = lineno;
      edata->funcname = funcname;
      /* the default text domain is the backend's */
!     edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
      /* Select default errcode based on elevel */
      if (elevel >= ERROR)
          edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;

pgsql-hackers by date:

Previous
From: Simon Riggs
Date:
Subject: Re: Hot standby, slot ids and stuff
Next
From: Michael Glaesemann
Date:
Subject: Re: Proposal: new border setting in psql