]> granicus.if.org Git - postgresql/blobdiff - src/port/chklocale.c
Fix whitespace
[postgresql] / src / port / chklocale.c
index cd911b84cee56a0ce33f762773f74e3a08cfd371..3c9d7abcbd7fd580b5efa33ab602a89521c327a5 100644 (file)
@@ -4,7 +4,7 @@
  *             Functions for handling locale-related info
  *
  *
- * Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Copyright (c) 1996-2013, PostgreSQL Global Development Group
  *
  *
  * IDENTIFICATION
@@ -162,6 +162,7 @@ static const struct encoding_match encoding_match_list[] = {
        {PG_SJIS, "SJIS"},
        {PG_SJIS, "PCK"},
        {PG_SJIS, "CP932"},
+       {PG_SJIS, "SHIFT_JIS"},
 
        {PG_BIG5, "BIG5"},
        {PG_BIG5, "BIG5HKSCS"},
@@ -189,29 +190,78 @@ static const struct encoding_match encoding_match_list[] = {
 
 #ifdef WIN32
 /*
- * On Windows, use CP<codepage number> instead of the nl_langinfo() result
+ * On Windows, use CP<code page number> instead of the nl_langinfo() result
+ *
+ * Visual Studio 2012 expanded the set of valid LC_CTYPE values, so have its
+ * locale machinery determine the code page.  See comments at IsoLocaleName().
+ * For other compilers, follow the locale's predictable format.
+ *
+ * Returns a malloc()'d string for the caller to free.
  */
 static char *
 win32_langinfo(const char *ctype)
 {
-       char       *r;
+       char       *r = NULL;
+
+#if (_MSC_VER >= 1700)
+       _locale_t       loct = NULL;
+
+       loct = _create_locale(LC_CTYPE, ctype);
+       if (loct != NULL)
+       {
+               r = malloc(16);                 /* excess */
+               if (r != NULL)
+                       sprintf(r, "CP%u", loct->locinfo->lc_codepage);
+               _free_locale(loct);
+       }
+#else
        char       *codepage;
-       int                     ln;
 
        /*
         * Locale format on Win32 is <Language>_<Country>.<CodePage> . For
-        * example, English_USA.1252.
+        * example, English_United States.1252.
         */
        codepage = strrchr(ctype, '.');
-       if (!codepage)
-               return NULL;
-       codepage++;
-       ln = strlen(codepage);
-       r = malloc(ln + 3);
-       sprintf(r, "CP%s", codepage);
+       if (codepage != NULL)
+       {
+               int                     ln;
+
+               codepage++;
+               ln = strlen(codepage);
+               r = malloc(ln + 3);
+               if (r != NULL)
+                       sprintf(r, "CP%s", codepage);
+       }
+#endif
 
        return r;
 }
+
+#ifndef FRONTEND
+/*
+ * Given a Windows code page identifier, find the corresponding PostgreSQL
+ * encoding.  Issue a warning and return -1 if none found.
+ */
+int
+pg_codepage_to_encoding(UINT cp)
+{
+       char            sys[16];
+       int                     i;
+
+       sprintf(sys, "CP%u", cp);
+
+       /* Check the table */
+       for (i = 0; encoding_match_list[i].system_enc_name; i++)
+               if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+                       return encoding_match_list[i].pg_enc_code;
+
+       ereport(WARNING,
+                       (errmsg("could not determine encoding for codeset \"%s\"", sys),
+                  errdetail("Please report this to <pgsql-bugs@postgresql.org>.")));
+
+       return -1;
+}
+#endif
 #endif   /* WIN32 */
 
 #if (defined(HAVE_LANGINFO_H) && defined(CODESET)) || defined(WIN32)
@@ -225,6 +275,9 @@ win32_langinfo(const char *ctype)
  *
  * If the result is PG_SQL_ASCII, callers should treat it as being compatible
  * with any desired encoding.
+ *
+ * If running in the backend and write_message is false, this function must
+ * cope with the possibility that elog() and palloc() are not yet usable.
  */
 int
 pg_get_encoding_from_locale(const char *ctype, bool write_message)
@@ -356,109 +409,3 @@ pg_get_encoding_from_locale(const char *ctype, bool write_message)
 }
 
 #endif   /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
-
-#ifdef WIN32
-/*
- * 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.
- */
-
-#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;
-}
-
-#endif   /* WIN32 */