Revert "Update gnulib to current upstream master"
[external/binutils.git] / gdb / gnulib / import / localcharset.c
index 58c5718..b2a0369 100644 (file)
@@ -1,6 +1,6 @@
 /* Determine a canonical name for the current locale's character encoding.
 
-   Copyright (C) 2000-2006, 2008-2018 Free Software Foundation, Inc.
+   Copyright (C) 2000-2006, 2008-2016 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License along
-   with this program; if not, see <https://www.gnu.org/licenses/>.  */
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>.  */
 
@@ -22,6 +22,7 @@
 /* Specification.  */
 #include "localcharset.h"
 
+#include <fcntl.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
@@ -31,7 +32,7 @@
 # define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */
 #endif
 
-#if defined _WIN32 && !defined __CYGWIN__
+#if defined _WIN32 || defined __WIN32__
 # define WINDOWS_NATIVE
 # include <locale.h>
 #endif
 #endif
 
 #if !defined WINDOWS_NATIVE
+# include <unistd.h>
 # if HAVE_LANGINFO_CODESET
 #  include <langinfo.h>
 # else
-#  if 0 /* see comment regarding use of setlocale(), below */
+#  if 0 /* see comment below */
 #   include <locale.h>
 #  endif
 # endif
 # include <xlocale.h>
 #endif
 
+#if ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+/* Get LIBDIR.  */
+#ifndef LIBDIR
+# include "configmake.h"
+#endif
+
+/* Define O_NOFOLLOW to 0 on platforms where it does not exist.  */
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+  /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
 
-#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
 
-/* On these platforms, we use a mapping from non-canonical encoding name
-   to GNU canonical encoding name.  */
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
 
-/* With glibc-2.1 or newer, we don't need any canonicalization,
-   because glibc has iconv and both glibc and libiconv support all
-   GNU canonical names directly.  */
-# if !((defined __GNU_LIBRARY__ && __GLIBC__ >= 2) || defined __UCLIBC__)
+#if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
 
-struct table_entry
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases (void)
 {
-  const char alias[11+1];
-  const char canonical[11+1];
-};
-
-/* Table of platform-dependent mappings, sorted in ascending order.  */
-static const struct table_entry alias_table[] =
-  {
-#  if defined __FreeBSD__                                   /* FreeBSD */
-  /*{ "ARMSCII-8",  "ARMSCII-8" },*/
-    { "Big5",       "BIG5" },
-    { "C",          "ASCII" },
-  /*{ "CP1131",     "CP1131" },*/
-  /*{ "CP1251",     "CP1251" },*/
-  /*{ "CP866",      "CP866" },*/
-  /*{ "GB18030",    "GB18030" },*/
-  /*{ "GB2312",     "GB2312" },*/
-  /*{ "GBK",        "GBK" },*/
-  /*{ "ISCII-DEV",  "?" },*/
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-13", "ISO-8859-13" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" },
-    { "ISO8859-9",  "ISO-8859-9" },
-  /*{ "KOI8-R",     "KOI8-R" },*/
-  /*{ "KOI8-U",     "KOI8-U" },*/
-    { "SJIS",       "SHIFT_JIS" },
-    { "US-ASCII",   "ASCII" },
-    { "eucCN",      "GB2312" },
-    { "eucJP",      "EUC-JP" },
-    { "eucKR",      "EUC-KR" }
-#   define alias_table_defined
-#  endif
-#  if defined __NetBSD__                                    /* NetBSD */
-    { "646",        "ASCII" },
-  /*{ "ARMSCII-8",  "ARMSCII-8" },*/
-  /*{ "BIG5",       "BIG5" },*/
-    { "Big5-HKSCS", "BIG5-HKSCS" },
-  /*{ "CP1251",     "CP1251" },*/
-  /*{ "CP866",      "CP866" },*/
-  /*{ "GB18030",    "GB18030" },*/
-  /*{ "GB2312",     "GB2312" },*/
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-13", "ISO-8859-13" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-4",  "ISO-8859-4" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" },
-  /*{ "KOI8-R",     "KOI8-R" },*/
-  /*{ "KOI8-U",     "KOI8-U" },*/
-  /*{ "PT154",      "PT154" },*/
-    { "SJIS",       "SHIFT_JIS" },
-    { "eucCN",      "GB2312" },
-    { "eucJP",      "EUC-JP" },
-    { "eucKR",      "EUC-KR" },
-    { "eucTW",      "EUC-TW" }
-#   define alias_table_defined
-#  endif
-#  if defined __OpenBSD__                                   /* OpenBSD */
-    { "646",        "ASCII" },
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-13", "ISO-8859-13" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-4",  "ISO-8859-4" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" }
-#   define alias_table_defined
-#  endif
-#  if defined __APPLE__ && defined __MACH__                 /* Mac OS X */
-    /* Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
-       useless:
-       - It returns the empty string when LANG is set to a locale of the
-         form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
-         LC_CTYPE file.
-       - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
-         the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
-       - The documentation says:
-           "... all code that calls BSD system routines should ensure
-            that the const *char parameters of these routines are in UTF-8
-            encoding. All BSD system functions expect their string
-            parameters to be in UTF-8 encoding and nothing else."
-         It also says
-           "An additional caveat is that string parameters for files,
-            paths, and other file-system entities must be in canonical
-            UTF-8. In a canonical UTF-8 Unicode string, all decomposable
-            characters are decomposed ..."
-         but this is not true: You can pass non-decomposed UTF-8 strings
-         to file system functions, and it is the OS which will convert
-         them to decomposed UTF-8 before accessing the file system.
-       - The Apple Terminal application displays UTF-8 by default.
-       - However, other applications are free to use different encodings:
-         - xterm uses ISO-8859-1 by default.
-         - TextEdit uses MacRoman by default.
-       We prefer UTF-8 over decomposed UTF-8-MAC because one should
-       minimize the use of decomposed Unicode. Unfortunately, through the
-       Darwin file system, decomposed UTF-8 strings are leaked into user
-       space nevertheless.
-       Then there are also the locales with encodings other than US-ASCII
-       and UTF-8. These locales can be occasionally useful to users (e.g.
-       when grepping through ISO-8859-1 encoded text files), when all their
-       file names are in US-ASCII.
-     */
-    { "ARMSCII-8",  "ARMSCII-8" },
-    { "Big5",       "BIG5" },
-    { "Big5HKSCS",  "BIG5-HKSCS" },
-    { "CP1131",     "CP1131" },
-    { "CP1251",     "CP1251" },
-    { "CP866",      "CP866" },
-    { "CP949",      "CP949" },
-    { "GB18030",    "GB18030" },
-    { "GB2312",     "GB2312" },
-    { "GBK",        "GBK" },
-  /*{ "ISCII-DEV",  "?" },*/
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-13", "ISO-8859-13" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-4",  "ISO-8859-4" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" },
-    { "ISO8859-9",  "ISO-8859-9" },
-    { "KOI8-R",     "KOI8-R" },
-    { "KOI8-U",     "KOI8-U" },
-    { "PT154",      "PT154" },
-    { "SJIS",       "SHIFT_JIS" },
-    { "eucCN",      "GB2312" },
-    { "eucJP",      "EUC-JP" },
-    { "eucKR",      "EUC-KR" }
-#   define alias_table_defined
-#  endif
-#  if defined _AIX                                          /* AIX */
-  /*{ "GBK",        "GBK" },*/
-    { "IBM-1046",   "CP1046" },
-    { "IBM-1124",   "CP1124" },
-    { "IBM-1129",   "CP1129" },
-    { "IBM-1252",   "CP1252" },
-    { "IBM-850",    "CP850" },
-    { "IBM-856",    "CP856" },
-    { "IBM-921",    "ISO-8859-13" },
-    { "IBM-922",    "CP922" },
-    { "IBM-932",    "CP932" },
-    { "IBM-943",    "CP943" },
-    { "IBM-eucCN",  "GB2312" },
-    { "IBM-eucJP",  "EUC-JP" },
-    { "IBM-eucKR",  "EUC-KR" },
-    { "IBM-eucTW",  "EUC-TW" },
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-6",  "ISO-8859-6" },
-    { "ISO8859-7",  "ISO-8859-7" },
-    { "ISO8859-8",  "ISO-8859-8" },
-    { "ISO8859-9",  "ISO-8859-9" },
-    { "TIS-620",    "TIS-620" },
-  /*{ "UTF-8",      "UTF-8" },*/
-    { "big5",       "BIG5" }
-#   define alias_table_defined
-#  endif
-#  if defined __hpux                                        /* HP-UX */
-    { "SJIS",      "SHIFT_JIS" },
-    { "arabic8",   "HP-ARABIC8" },
-    { "big5",      "BIG5" },
-    { "cp1251",    "CP1251" },
-    { "eucJP",     "EUC-JP" },
-    { "eucKR",     "EUC-KR" },
-    { "eucTW",     "EUC-TW" },
-    { "gb18030",   "GB18030" },
-    { "greek8",    "HP-GREEK8" },
-    { "hebrew8",   "HP-HEBREW8" },
-    { "hkbig5",    "BIG5-HKSCS" },
-    { "hp15CN",    "GB2312" },
-    { "iso88591",  "ISO-8859-1" },
-    { "iso885913", "ISO-8859-13" },
-    { "iso885915", "ISO-8859-15" },
-    { "iso88592",  "ISO-8859-2" },
-    { "iso88594",  "ISO-8859-4" },
-    { "iso88595",  "ISO-8859-5" },
-    { "iso88596",  "ISO-8859-6" },
-    { "iso88597",  "ISO-8859-7" },
-    { "iso88598",  "ISO-8859-8" },
-    { "iso88599",  "ISO-8859-9" },
-    { "kana8",     "HP-KANA8" },
-    { "koi8r",     "KOI8-R" },
-    { "roman8",    "HP-ROMAN8" },
-    { "tis620",    "TIS-620" },
-    { "turkish8",  "HP-TURKISH8" },
-    { "utf8",      "UTF-8" }
-#   define alias_table_defined
-#  endif
-#  if defined __sgi                                         /* IRIX */
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" },
-    { "ISO8859-9",  "ISO-8859-9" },
-    { "eucCN",      "GB2312" },
-    { "eucJP",      "EUC-JP" },
-    { "eucKR",      "EUC-KR" },
-    { "eucTW",      "EUC-TW" }
-#   define alias_table_defined
-#  endif
-#  if defined __osf__                                       /* OSF/1 */
-  /*{ "GBK",        "GBK" },*/
-    { "ISO8859-1",  "ISO-8859-1" },
-    { "ISO8859-15", "ISO-8859-15" },
-    { "ISO8859-2",  "ISO-8859-2" },
-    { "ISO8859-4",  "ISO-8859-4" },
-    { "ISO8859-5",  "ISO-8859-5" },
-    { "ISO8859-7",  "ISO-8859-7" },
-    { "ISO8859-8",  "ISO-8859-8" },
-    { "ISO8859-9",  "ISO-8859-9" },
-    { "KSC5601",    "CP949" },
-    { "SJIS",       "SHIFT_JIS" },
-    { "TACTIS",     "TIS-620" },
-  /*{ "UTF-8",      "UTF-8" },*/
-    { "big5",       "BIG5" },
-    { "cp850",      "CP850" },
-    { "dechanyu",   "DEC-HANYU" },
-    { "dechanzi",   "GB2312" },
-    { "deckanji",   "DEC-KANJI" },
-    { "deckorean",  "EUC-KR" },
-    { "eucJP",      "EUC-JP" },
-    { "eucKR",      "EUC-KR" },
-    { "eucTW",      "EUC-TW" },
-    { "sdeckanji",  "EUC-JP" }
-#   define alias_table_defined
-#  endif
-#  if defined __sun                                         /* Solaris */
-    { "5601",        "EUC-KR" },
-    { "646",         "ASCII" },
-  /*{ "BIG5",        "BIG5" },*/
-    { "Big5-HKSCS",  "BIG5-HKSCS" },
-    { "GB18030",     "GB18030" },
-  /*{ "GBK",         "GBK" },*/
-    { "ISO8859-1",   "ISO-8859-1" },
-    { "ISO8859-11",  "TIS-620" },
-    { "ISO8859-13",  "ISO-8859-13" },
-    { "ISO8859-15",  "ISO-8859-15" },
-    { "ISO8859-2",   "ISO-8859-2" },
-    { "ISO8859-3",   "ISO-8859-3" },
-    { "ISO8859-4",   "ISO-8859-4" },
-    { "ISO8859-5",   "ISO-8859-5" },
-    { "ISO8859-6",   "ISO-8859-6" },
-    { "ISO8859-7",   "ISO-8859-7" },
-    { "ISO8859-8",   "ISO-8859-8" },
-    { "ISO8859-9",   "ISO-8859-9" },
-    { "PCK",         "SHIFT_JIS" },
-    { "TIS620.2533", "TIS-620" },
-  /*{ "UTF-8",       "UTF-8" },*/
-    { "ansi-1251",   "CP1251" },
-    { "cns11643",    "EUC-TW" },
-    { "eucJP",       "EUC-JP" },
-    { "gb2312",      "GB2312" },
-    { "koi8-r",      "KOI8-R" }
-#   define alias_table_defined
-#  endif
-#  if defined __minix                                       /* Minix */
-    { "646", "ASCII" }
-#   define alias_table_defined
-#  endif
-#  if defined WINDOWS_NATIVE || defined __CYGWIN__          /* Windows */
-    { "CP1361",  "JOHAB" },
-    { "CP20127", "ASCII" },
-    { "CP20866", "KOI8-R" },
-    { "CP20936", "GB2312" },
-    { "CP21866", "KOI8-RU" },
-    { "CP28591", "ISO-8859-1" },
-    { "CP28592", "ISO-8859-2" },
-    { "CP28593", "ISO-8859-3" },
-    { "CP28594", "ISO-8859-4" },
-    { "CP28595", "ISO-8859-5" },
-    { "CP28596", "ISO-8859-6" },
-    { "CP28597", "ISO-8859-7" },
-    { "CP28598", "ISO-8859-8" },
-    { "CP28599", "ISO-8859-9" },
-    { "CP28605", "ISO-8859-15" },
-    { "CP38598", "ISO-8859-8" },
-    { "CP51932", "EUC-JP" },
-    { "CP51936", "GB2312" },
-    { "CP51949", "EUC-KR" },
-    { "CP51950", "EUC-TW" },
-    { "CP54936", "GB18030" },
-    { "CP65001", "UTF-8" },
-    { "CP936",   "GBK" }
-#   define alias_table_defined
-#  endif
-#  if defined OS2                                           /* OS/2 */
-    /* The list of encodings is taken from "List of OS/2 Codepages"
-       by Alex Taylor:
-       <http://altsan.org/os2/toolkits/uls/index.html#codepages>.
-       See also "IBM Globalization - Code page identifiers":
-       <https://www-01.ibm.com/software/globalization/cp/cp_cpgid.html>.  */
-    { "CP1089", "ISO-8859-6" },
-    { "CP1208", "UTF-8" },
-    { "CP1381", "GB2312" },
-    { "CP1386", "GBK" },
-    { "CP3372", "EUC-JP" },
-    { "CP813",  "ISO-8859-7" },
-    { "CP819",  "ISO-8859-1" },
-    { "CP878",  "KOI8-R" },
-    { "CP912",  "ISO-8859-2" },
-    { "CP913",  "ISO-8859-3" },
-    { "CP914",  "ISO-8859-4" },
-    { "CP915",  "ISO-8859-5" },
-    { "CP916",  "ISO-8859-8" },
-    { "CP920",  "ISO-8859-9" },
-    { "CP921",  "ISO-8859-13" },
-    { "CP923",  "ISO-8859-15" },
-    { "CP954",  "EUC-JP" },
-    { "CP964",  "EUC-TW" },
-    { "CP970",  "EUC-KR" }
-#   define alias_table_defined
-#  endif
-#  if defined VMS                                           /* OpenVMS */
-    /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
-       "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
-       section 10.7 "Handling Different Character Sets".  */
-    { "DECHANYU",  "DEC-HANYU" },
-    { "DECHANZI",  "GB2312" },
-    { "DECKANJI",  "DEC-KANJI" },
-    { "DECKOREAN", "EUC-KR" },
-    { "ISO8859-1", "ISO-8859-1" },
-    { "ISO8859-2", "ISO-8859-2" },
-    { "ISO8859-5", "ISO-8859-5" },
-    { "ISO8859-7", "ISO-8859-7" },
-    { "ISO8859-8", "ISO-8859-8" },
-    { "ISO8859-9", "ISO-8859-9" },
-    { "SDECKANJI", "EUC-JP" },
-    { "SJIS",      "SHIFT_JIS" },
-    { "eucJP",     "EUC-JP" },
-    { "eucTW",     "EUC-TW" }
-#   define alias_table_defined
-#  endif
-#  ifndef alias_table_defined
-    /* Just a dummy entry, to avoid a C syntax error.  */
-    { "", "" }
-#  endif
-  };
+  const char *cp;
 
-# endif
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__ || defined OS2)
+      const char *dir;
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Make it possible to override the charset.alias location.  This is
+         necessary for running the testsuite before "make install".  */
+      dir = getenv ("CHARSETALIASDIR");
+      if (dir == NULL || dir[0] == '\0')
+        dir = relocate (LIBDIR);
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+        size_t dir_len = strlen (dir);
+        size_t base_len = strlen (base);
+        int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+        file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+        if (file_name != NULL)
+          {
+            memcpy (file_name, dir, dir_len);
+            if (add_slash)
+              file_name[dir_len] = DIRECTORY_SEPARATOR;
+            memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+          }
+      }
+
+      if (file_name == NULL)
+        /* Out of memory.  Treat the file as empty.  */
+        cp = "";
+      else
+        {
+          int fd;
+
+          /* Open the file.  Reject symbolic links on platforms that support
+             O_NOFOLLOW.  This is a security feature.  Without it, an attacker
+             could retrieve parts of the contents (namely, the tail of the
+             first line that starts with "* ") of an arbitrary file by placing
+             a symbolic link to that file under the name "charset.alias" in
+             some writable directory and defining the environment variable
+             CHARSETALIASDIR to point to that directory.  */
+          fd = open (file_name,
+                     O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0));
+          if (fd < 0)
+            /* File not found.  Treat it as empty.  */
+            cp = "";
+          else
+            {
+              FILE *fp;
+
+              fp = fdopen (fd, "r");
+              if (fp == NULL)
+                {
+                  /* Out of memory.  Treat the file as empty.  */
+                  close (fd);
+                  cp = "";
+                }
+              else
+                {
+                  /* Parse the file's contents.  */
+                  char *res_ptr = NULL;
+                  size_t res_size = 0;
+
+                  for (;;)
+                    {
+                      int c;
+                      char buf1[50+1];
+                      char buf2[50+1];
+                      size_t l1, l2;
+                      char *old_res_ptr;
+
+                      c = getc (fp);
+                      if (c == EOF)
+                        break;
+                      if (c == '\n' || c == ' ' || c == '\t')
+                        continue;
+                      if (c == '#')
+                        {
+                          /* Skip comment, to end of line.  */
+                          do
+                            c = getc (fp);
+                          while (!(c == EOF || c == '\n'));
+                          if (c == EOF)
+                            break;
+                          continue;
+                        }
+                      ungetc (c, fp);
+                      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+                        break;
+                      l1 = strlen (buf1);
+                      l2 = strlen (buf2);
+                      old_res_ptr = res_ptr;
+                      if (res_size == 0)
+                        {
+                          res_size = l1 + 1 + l2 + 1;
+                          res_ptr = (char *) malloc (res_size + 1);
+                        }
+                      else
+                        {
+                          res_size += l1 + 1 + l2 + 1;
+                          res_ptr = (char *) realloc (res_ptr, res_size + 1);
+                        }
+                      if (res_ptr == NULL)
+                        {
+                          /* Out of memory. */
+                          res_size = 0;
+                          free (old_res_ptr);
+                          break;
+                        }
+                      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+                      strcpy (res_ptr + res_size - (l2 + 1), buf2);
+                    }
+                  fclose (fp);
+                  if (res_size == 0)
+                    cp = "";
+                  else
+                    {
+                      *(res_ptr + res_size) = '\0';
+                      cp = res_ptr;
+                    }
+                }
+            }
+
+          free (file_name);
+        }
 
 #else
 
-/* On these platforms, we use a mapping from locale name to GNU canonical
-   encoding name.  */
+# if defined DARWIN7
+      /* To avoid the trouble of installing a file that is shared by many
+         GNU packages -- many packaging systems have problems with this --,
+         simply inline the aliases here.  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+           "ISO8859-2" "\0" "ISO-8859-2" "\0"
+           "ISO8859-4" "\0" "ISO-8859-4" "\0"
+           "ISO8859-5" "\0" "ISO-8859-5" "\0"
+           "ISO8859-7" "\0" "ISO-8859-7" "\0"
+           "ISO8859-9" "\0" "ISO-8859-9" "\0"
+           "ISO8859-13" "\0" "ISO-8859-13" "\0"
+           "ISO8859-15" "\0" "ISO-8859-15" "\0"
+           "KOI8-R" "\0" "KOI8-R" "\0"
+           "KOI8-U" "\0" "KOI8-U" "\0"
+           "CP866" "\0" "CP866" "\0"
+           "CP949" "\0" "CP949" "\0"
+           "CP1131" "\0" "CP1131" "\0"
+           "CP1251" "\0" "CP1251" "\0"
+           "eucCN" "\0" "GB2312" "\0"
+           "GB2312" "\0" "GB2312" "\0"
+           "eucJP" "\0" "EUC-JP" "\0"
+           "eucKR" "\0" "EUC-KR" "\0"
+           "Big5" "\0" "BIG5" "\0"
+           "Big5HKSCS" "\0" "BIG5-HKSCS" "\0"
+           "GBK" "\0" "GBK" "\0"
+           "GB18030" "\0" "GB18030" "\0"
+           "SJIS" "\0" "SHIFT_JIS" "\0"
+           "ARMSCII-8" "\0" "ARMSCII-8" "\0"
+           "PT154" "\0" "PT154" "\0"
+         /*"ISCII-DEV" "\0" "?" "\0"*/
+           "*" "\0" "UTF-8" "\0";
+# endif
 
-struct table_entry
-{
-  const char locale[17+1];
-  const char canonical[11+1];
-};
-
-/* Table of platform-dependent mappings, sorted in ascending order.  */
-static const struct table_entry locale_table[] =
-  {
-# if defined __FreeBSD__                                    /* FreeBSD 4.2 */
-    { "cs_CZ.ISO_8859-2",  "ISO-8859-2" },
-    { "da_DK.DIS_8859-15", "ISO-8859-15" },
-    { "da_DK.ISO_8859-1",  "ISO-8859-1" },
-    { "de_AT.DIS_8859-15", "ISO-8859-15" },
-    { "de_AT.ISO_8859-1",  "ISO-8859-1" },
-    { "de_CH.DIS_8859-15", "ISO-8859-15" },
-    { "de_CH.ISO_8859-1",  "ISO-8859-1" },
-    { "de_DE.DIS_8859-15", "ISO-8859-15" },
-    { "de_DE.ISO_8859-1",  "ISO-8859-1" },
-    { "en_AU.DIS_8859-15", "ISO-8859-15" },
-    { "en_AU.ISO_8859-1",  "ISO-8859-1" },
-    { "en_CA.DIS_8859-15", "ISO-8859-15" },
-    { "en_CA.ISO_8859-1",  "ISO-8859-1" },
-    { "en_GB.DIS_8859-15", "ISO-8859-15" },
-    { "en_GB.ISO_8859-1",  "ISO-8859-1" },
-    { "en_US.DIS_8859-15", "ISO-8859-15" },
-    { "en_US.ISO_8859-1",  "ISO-8859-1" },
-    { "es_ES.DIS_8859-15", "ISO-8859-15" },
-    { "es_ES.ISO_8859-1",  "ISO-8859-1" },
-    { "fi_FI.DIS_8859-15", "ISO-8859-15" },
-    { "fi_FI.ISO_8859-1",  "ISO-8859-1" },
-    { "fr_BE.DIS_8859-15", "ISO-8859-15" },
-    { "fr_BE.ISO_8859-1",  "ISO-8859-1" },
-    { "fr_CA.DIS_8859-15", "ISO-8859-15" },
-    { "fr_CA.ISO_8859-1",  "ISO-8859-1" },
-    { "fr_CH.DIS_8859-15", "ISO-8859-15" },
-    { "fr_CH.ISO_8859-1",  "ISO-8859-1" },
-    { "fr_FR.DIS_8859-15", "ISO-8859-15" },
-    { "fr_FR.ISO_8859-1",  "ISO-8859-1" },
-    { "hr_HR.ISO_8859-2",  "ISO-8859-2" },
-    { "hu_HU.ISO_8859-2",  "ISO-8859-2" },
-    { "is_IS.DIS_8859-15", "ISO-8859-15" },
-    { "is_IS.ISO_8859-1",  "ISO-8859-1" },
-    { "it_CH.DIS_8859-15", "ISO-8859-15" },
-    { "it_CH.ISO_8859-1",  "ISO-8859-1" },
-    { "it_IT.DIS_8859-15", "ISO-8859-15" },
-    { "it_IT.ISO_8859-1",  "ISO-8859-1" },
-    { "ja_JP.EUC",         "EUC-JP" },
-    { "ja_JP.SJIS",        "SHIFT_JIS" },
-    { "ja_JP.Shift_JIS",   "SHIFT_JIS" },
-    { "ko_KR.EUC",         "EUC-KR" },
-    { "la_LN.ASCII",       "ASCII" },
-    { "la_LN.DIS_8859-15", "ISO-8859-15" },
-    { "la_LN.ISO_8859-1",  "ISO-8859-1" },
-    { "la_LN.ISO_8859-2",  "ISO-8859-2" },
-    { "la_LN.ISO_8859-4",  "ISO-8859-4" },
-    { "lt_LN.ASCII",       "ASCII" },
-    { "lt_LN.DIS_8859-15", "ISO-8859-15" },
-    { "lt_LN.ISO_8859-1",  "ISO-8859-1" },
-    { "lt_LN.ISO_8859-2",  "ISO-8859-2" },
-    { "lt_LT.ISO_8859-4",  "ISO-8859-4" },
-    { "nl_BE.DIS_8859-15", "ISO-8859-15" },
-    { "nl_BE.ISO_8859-1",  "ISO-8859-1" },
-    { "nl_NL.DIS_8859-15", "ISO-8859-15" },
-    { "nl_NL.ISO_8859-1",  "ISO-8859-1" },
-    { "no_NO.DIS_8859-15", "ISO-8859-15" },
-    { "no_NO.ISO_8859-1",  "ISO-8859-1" },
-    { "pl_PL.ISO_8859-2",  "ISO-8859-2" },
-    { "pt_PT.DIS_8859-15", "ISO-8859-15" },
-    { "pt_PT.ISO_8859-1",  "ISO-8859-1" },
-    { "ru_RU.CP866",       "CP866" },
-    { "ru_RU.ISO_8859-5",  "ISO-8859-5" },
-    { "ru_RU.KOI8-R",      "KOI8-R" },
-    { "ru_SU.CP866",       "CP866" },
-    { "ru_SU.ISO_8859-5",  "ISO-8859-5" },
-    { "ru_SU.KOI8-R",      "KOI8-R" },
-    { "sl_SI.ISO_8859-2",  "ISO-8859-2" },
-    { "sv_SE.DIS_8859-15", "ISO-8859-15" },
-    { "sv_SE.ISO_8859-1",  "ISO-8859-1" },
-    { "uk_UA.KOI8-U",      "KOI8-U" },
-    { "zh_CN.EUC",         "GB2312" },
-    { "zh_TW.BIG5",        "BIG5" },
-    { "zh_TW.Big5",        "BIG5" }
-#  define locale_table_defined
+# if defined VMS
+      /* To avoid the troubles of an extra file charset.alias_vms in the
+         sources of many GNU packages, simply inline the aliases here.  */
+      /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
+         "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
+         section 10.7 "Handling Different Character Sets".  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+           "ISO8859-2" "\0" "ISO-8859-2" "\0"
+           "ISO8859-5" "\0" "ISO-8859-5" "\0"
+           "ISO8859-7" "\0" "ISO-8859-7" "\0"
+           "ISO8859-8" "\0" "ISO-8859-8" "\0"
+           "ISO8859-9" "\0" "ISO-8859-9" "\0"
+           /* Japanese */
+           "eucJP" "\0" "EUC-JP" "\0"
+           "SJIS" "\0" "SHIFT_JIS" "\0"
+           "DECKANJI" "\0" "DEC-KANJI" "\0"
+           "SDECKANJI" "\0" "EUC-JP" "\0"
+           /* Chinese */
+           "eucTW" "\0" "EUC-TW" "\0"
+           "DECHANYU" "\0" "DEC-HANYU" "\0"
+           "DECHANZI" "\0" "GB2312" "\0"
+           /* Korean */
+           "DECKOREAN" "\0" "EUC-KR" "\0";
 # endif
-# if defined __DJGPP__                                      /* DOS / DJGPP 2.03 */
-    /* The encodings given here may not all be correct.
-       If you find that the encoding given for your language and
-       country is not the one your DOS machine actually uses, just
-       correct it in this file, and send a mail to
-       Juan Manuel Guerrero <juan.guerrero@gmx.de>
-       and <bug-gnulib@gnu.org>.  */
-    { "C",     "ASCII" },
-    { "ar",    "CP864" },
-    { "ar_AE", "CP864" },
-    { "ar_DZ", "CP864" },
-    { "ar_EG", "CP864" },
-    { "ar_IQ", "CP864" },
-    { "ar_IR", "CP864" },
-    { "ar_JO", "CP864" },
-    { "ar_KW", "CP864" },
-    { "ar_MA", "CP864" },
-    { "ar_OM", "CP864" },
-    { "ar_QA", "CP864" },
-    { "ar_SA", "CP864" },
-    { "ar_SY", "CP864" },
-    { "be",    "CP866" },
-    { "be_BE", "CP866" },
-    { "bg",    "CP866" }, /* not CP855 ?? */
-    { "bg_BG", "CP866" }, /* not CP855 ?? */
-    { "ca",    "CP850" },
-    { "ca_ES", "CP850" },
-    { "cs",    "CP852" },
-    { "cs_CZ", "CP852" },
-    { "da",    "CP865" }, /* not CP850 ?? */
-    { "da_DK", "CP865" }, /* not CP850 ?? */
-    { "de",    "CP850" },
-    { "de_AT", "CP850" },
-    { "de_CH", "CP850" },
-    { "de_DE", "CP850" },
-    { "el",    "CP869" },
-    { "el_GR", "CP869" },
-    { "en",    "CP850" },
-    { "en_AU", "CP850" }, /* not CP437 ?? */
-    { "en_CA", "CP850" },
-    { "en_GB", "CP850" },
-    { "en_NZ", "CP437" },
-    { "en_US", "CP437" },
-    { "en_ZA", "CP850" }, /* not CP437 ?? */
-    { "eo",    "CP850" },
-    { "eo_EO", "CP850" },
-    { "es",    "CP850" },
-    { "es_AR", "CP850" },
-    { "es_BO", "CP850" },
-    { "es_CL", "CP850" },
-    { "es_CO", "CP850" },
-    { "es_CR", "CP850" },
-    { "es_CU", "CP850" },
-    { "es_DO", "CP850" },
-    { "es_EC", "CP850" },
-    { "es_ES", "CP850" },
-    { "es_GT", "CP850" },
-    { "es_HN", "CP850" },
-    { "es_MX", "CP850" },
-    { "es_NI", "CP850" },
-    { "es_PA", "CP850" },
-    { "es_PE", "CP850" },
-    { "es_PY", "CP850" },
-    { "es_SV", "CP850" },
-    { "es_UY", "CP850" },
-    { "es_VE", "CP850" },
-    { "et",    "CP850" },
-    { "et_EE", "CP850" },
-    { "eu",    "CP850" },
-    { "eu_ES", "CP850" },
-    { "fi",    "CP850" },
-    { "fi_FI", "CP850" },
-    { "fr",    "CP850" },
-    { "fr_BE", "CP850" },
-    { "fr_CA", "CP850" },
-    { "fr_CH", "CP850" },
-    { "fr_FR", "CP850" },
-    { "ga",    "CP850" },
-    { "ga_IE", "CP850" },
-    { "gd",    "CP850" },
-    { "gd_GB", "CP850" },
-    { "gl",    "CP850" },
-    { "gl_ES", "CP850" },
-    { "he",    "CP862" },
-    { "he_IL", "CP862" },
-    { "hr",    "CP852" },
-    { "hr_HR", "CP852" },
-    { "hu",    "CP852" },
-    { "hu_HU", "CP852" },
-    { "id",    "CP850" }, /* not CP437 ?? */
-    { "id_ID", "CP850" }, /* not CP437 ?? */
-    { "is",    "CP861" }, /* not CP850 ?? */
-    { "is_IS", "CP861" }, /* not CP850 ?? */
-    { "it",    "CP850" },
-    { "it_CH", "CP850" },
-    { "it_IT", "CP850" },
-    { "ja",    "CP932" },
-    { "ja_JP", "CP932" },
-    { "kr",    "CP949" }, /* not CP934 ?? */
-    { "kr_KR", "CP949" }, /* not CP934 ?? */
-    { "lt",    "CP775" },
-    { "lt_LT", "CP775" },
-    { "lv",    "CP775" },
-    { "lv_LV", "CP775" },
-    { "mk",    "CP866" }, /* not CP855 ?? */
-    { "mk_MK", "CP866" }, /* not CP855 ?? */
-    { "mt",    "CP850" },
-    { "mt_MT", "CP850" },
-    { "nb",    "CP865" }, /* not CP850 ?? */
-    { "nb_NO", "CP865" }, /* not CP850 ?? */
-    { "nl",    "CP850" },
-    { "nl_BE", "CP850" },
-    { "nl_NL", "CP850" },
-    { "nn",    "CP865" }, /* not CP850 ?? */
-    { "nn_NO", "CP865" }, /* not CP850 ?? */
-    { "no",    "CP865" }, /* not CP850 ?? */
-    { "no_NO", "CP865" }, /* not CP850 ?? */
-    { "pl",    "CP852" },
-    { "pl_PL", "CP852" },
-    { "pt",    "CP850" },
-    { "pt_BR", "CP850" },
-    { "pt_PT", "CP850" },
-    { "ro",    "CP852" },
-    { "ro_RO", "CP852" },
-    { "ru",    "CP866" },
-    { "ru_RU", "CP866" },
-    { "sk",    "CP852" },
-    { "sk_SK", "CP852" },
-    { "sl",    "CP852" },
-    { "sl_SI", "CP852" },
-    { "sq",    "CP852" },
-    { "sq_AL", "CP852" },
-    { "sr",    "CP852" }, /* CP852 or CP866 or CP855 ?? */
-    { "sr_CS", "CP852" }, /* CP852 or CP866 or CP855 ?? */
-    { "sr_YU", "CP852" }, /* CP852 or CP866 or CP855 ?? */
-    { "sv",    "CP850" },
-    { "sv_SE", "CP850" },
-    { "th",    "CP874" },
-    { "th_TH", "CP874" },
-    { "tr",    "CP857" },
-    { "tr_TR", "CP857" },
-    { "uk",    "CP1125" },
-    { "uk_UA", "CP1125" },
-    { "zh_CN", "GBK" },
-    { "zh_TW", "CP950" } /* not CP938 ?? */
-#  define locale_table_defined
+
+# if defined WINDOWS_NATIVE || defined __CYGWIN__
+      /* To avoid the troubles of installing a separate file in the same
+         directory as the DLL and of retrieving the DLL's directory at
+         runtime, simply inline the aliases here.  */
+
+      cp = "CP936" "\0" "GBK" "\0"
+           "CP1361" "\0" "JOHAB" "\0"
+           "CP20127" "\0" "ASCII" "\0"
+           "CP20866" "\0" "KOI8-R" "\0"
+           "CP20936" "\0" "GB2312" "\0"
+           "CP21866" "\0" "KOI8-RU" "\0"
+           "CP28591" "\0" "ISO-8859-1" "\0"
+           "CP28592" "\0" "ISO-8859-2" "\0"
+           "CP28593" "\0" "ISO-8859-3" "\0"
+           "CP28594" "\0" "ISO-8859-4" "\0"
+           "CP28595" "\0" "ISO-8859-5" "\0"
+           "CP28596" "\0" "ISO-8859-6" "\0"
+           "CP28597" "\0" "ISO-8859-7" "\0"
+           "CP28598" "\0" "ISO-8859-8" "\0"
+           "CP28599" "\0" "ISO-8859-9" "\0"
+           "CP28605" "\0" "ISO-8859-15" "\0"
+           "CP38598" "\0" "ISO-8859-8" "\0"
+           "CP51932" "\0" "EUC-JP" "\0"
+           "CP51936" "\0" "GB2312" "\0"
+           "CP51949" "\0" "EUC-KR" "\0"
+           "CP51950" "\0" "EUC-TW" "\0"
+           "CP54936" "\0" "GB18030" "\0"
+           "CP65001" "\0" "UTF-8" "\0";
 # endif
-# ifndef locale_table_defined
-    /* Just a dummy entry, to avoid a C syntax error.  */
-    { "", "" }
+# if defined OS2
+      /* To avoid the troubles of installing a separate file in the same
+         directory as the DLL and of retrieving the DLL's directory at
+         runtime, simply inline the aliases here.  */
+
+      /* The list of encodings is taken from "List of OS/2 Codepages"
+         by Alex Taylor:
+         <http://altsan.org/os2/toolkits/uls/index.html#codepages>.
+         See also "IBM Globalization - Code page identifiers":
+         <http://www-01.ibm.com/software/globalization/cp/cp_cpgid.html>.  */
+      cp = "CP813" "\0" "ISO-8859-7" "\0"
+           "CP878" "\0" "KOI8-R" "\0"
+           "CP819" "\0" "ISO-8859-1" "\0"
+           "CP912" "\0" "ISO-8859-2" "\0"
+           "CP913" "\0" "ISO-8859-3" "\0"
+           "CP914" "\0" "ISO-8859-4" "\0"
+           "CP915" "\0" "ISO-8859-5" "\0"
+           "CP916" "\0" "ISO-8859-8" "\0"
+           "CP920" "\0" "ISO-8859-9" "\0"
+           "CP921" "\0" "ISO-8859-13" "\0"
+           "CP923" "\0" "ISO-8859-15" "\0"
+           "CP954" "\0" "EUC-JP" "\0"
+           "CP964" "\0" "EUC-TW" "\0"
+           "CP970" "\0" "EUC-KR" "\0"
+           "CP1089" "\0" "ISO-8859-6" "\0"
+           "CP1208" "\0" "UTF-8" "\0"
+           "CP1381" "\0" "GB2312" "\0"
+           "CP1386" "\0" "GBK" "\0"
+           "CP3372" "\0" "EUC-JP" "\0";
 # endif
-  };
-
 #endif
 
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
 
 /* Determine the current locale's character encoding, and canonicalize it
-   into one of the canonical names listed in localcharset.h.
+   into one of the canonical names listed in config.charset.
    The result must not be freed; it is statically allocated.
    If the canonical name cannot be determined, the result is a non-canonical
    name.  */
@@ -687,8 +393,9 @@ const char *
 locale_charset (void)
 {
   const char *codeset;
+  const char *aliases;
 
-#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
+#if !(defined WINDOWS_NATIVE || defined OS2)
 
 # if HAVE_LANGINFO_CODESET
 
@@ -751,11 +458,37 @@ locale_charset (void)
     }
 #  endif
 
-  if (codeset == NULL)
-    /* The canonical name cannot be determined.  */
-    codeset = "";
+# else
+
+  /* On old systems which lack it, use setlocale or getenv.  */
+  const char *locale = NULL;
+
+  /* But most old systems don't have a complete set of locales.  Some
+     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
+     use setlocale here; it would return "C" when it doesn't support the
+     locale name the user has set.  */
+#  if 0
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+        {
+          locale = getenv ("LC_CTYPE");
+          if (locale == NULL || locale[0] == '\0')
+            locale = getenv ("LANG");
+        }
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
 
-# elif defined WINDOWS_NATIVE
+# endif
+
+#elif defined WINDOWS_NATIVE
 
   static char buf[2 + 10 + 1];
 
@@ -774,7 +507,7 @@ locale_charset (void)
     current_locale = setlocale (LC_CTYPE, NULL);
 
   pdot = strrchr (current_locale, '.');
-  if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
+  if (pdot)
     sprintf (buf, "CP%s", pdot + 1);
   else
     {
@@ -789,7 +522,7 @@ locale_charset (void)
     }
   codeset = buf;
 
-# elif defined OS2
+#elif defined OS2
 
   const char *locale;
   static char buf[2 + 10 + 1];
@@ -846,144 +579,28 @@ locale_charset (void)
         }
     }
 
-# else
-
-#  error "Add code for other platforms here."
-
-# endif
-
-  /* Resolve alias.  */
-  {
-# ifdef alias_table_defined
-    /* On some platforms, UTF-8 locales are the most frequently used ones.
-       Speed up the common case and slow down the less common cases by
-       testing for this case first.  */
-#  if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__
-    if (strcmp (codeset, "UTF-8") == 0)
-      goto done_table_lookup;
-    else
-#  endif
-      {
-        const struct table_entry * const table = alias_table;
-        size_t const table_size =
-          sizeof (alias_table) / sizeof (struct table_entry);
-        /* The table is sorted.  Perform a binary search.  */
-        size_t hi = table_size;
-        size_t lo = 0;
-        while (lo < hi)
-          {
-            /* Invariant:
-               for i < lo, strcmp (table[i].alias, codeset) < 0,
-               for i >= hi, strcmp (table[i].alias, codeset) > 0.  */
-            size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
-            int cmp = strcmp (table[mid].alias, codeset);
-            if (cmp < 0)
-              lo = mid + 1;
-            else if (cmp > 0)
-              hi = mid;
-            else
-              {
-                /* Found an i with
-                     strcmp (table[i].alias, codeset) == 0.  */
-                codeset = table[mid].canonical;
-                goto done_table_lookup;
-              }
-          }
-      }
-    if (0)
-      done_table_lookup: ;
-    else
-# endif
-      {
-        /* Did not find it in the table.  */
-        /* On Mac OS X, all modern locales use the UTF-8 encoding.
-           BeOS and Haiku have a single locale, and it has UTF-8 encoding.  */
-# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
-        codeset = "UTF-8";
-# else
-        /* Don't return an empty string.  GNU libc and GNU libiconv interpret
-           the empty string as denoting "the locale's character encoding",
-           thus GNU libiconv would call this function a second time.  */
-        if (codeset[0] == '\0')
-          codeset = "ASCII";
-# endif
-      }
-  }
-
-#else
-
-  /* On old systems which lack it, use setlocale or getenv.  */
-  const char *locale = NULL;
+#endif
 
-  /* But most old systems don't have a complete set of locales.  Some
-     (like DJGPP) have only the C locale.  Therefore we don't use setlocale
-     here; it would return "C" when it doesn't support the locale name the
-     user has set.  */
-# if 0
-  locale = setlocale (LC_CTYPE, NULL);
-# endif
-  if (locale == NULL || locale[0] == '\0')
-    {
-      locale = getenv ("LC_ALL");
-      if (locale == NULL || locale[0] == '\0')
-        {
-          locale = getenv ("LC_CTYPE");
-          if (locale == NULL || locale[0] == '\0')
-            locale = getenv ("LANG");
-            if (locale == NULL)
-              locale = "";
-        }
-    }
+  if (codeset == NULL)
+    /* The canonical name cannot be determined.  */
+    codeset = "";
 
-  /* Map locale name to canonical encoding name.  */
-  {
-# ifdef locale_table_defined
-    const struct table_entry * const table = locale_table;
-    size_t const table_size =
-      sizeof (locale_table) / sizeof (struct table_entry);
-    /* The table is sorted.  Perform a binary search.  */
-    size_t hi = table_size;
-    size_t lo = 0;
-    while (lo < hi)
+  /* Resolve alias. */
+  for (aliases = get_charset_aliases ();
+       *aliases != '\0';
+       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+    if (strcmp (codeset, aliases) == 0
+        || (aliases[0] == '*' && aliases[1] == '\0'))
       {
-        /* Invariant:
-           for i < lo, strcmp (table[i].locale, locale) < 0,
-           for i >= hi, strcmp (table[i].locale, locale) > 0.  */
-        size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
-        int cmp = strcmp (table[mid].locale, locale);
-        if (cmp < 0)
-          lo = mid + 1;
-        else if (cmp > 0)
-          hi = mid;
-        else
-          {
-            /* Found an i with
-                 strcmp (table[i].locale, locale) == 0.  */
-            codeset = table[mid].canonical;
-            goto done_table_lookup;
-          }
+        codeset = aliases + strlen (aliases) + 1;
+        break;
       }
-    if (0)
-      done_table_lookup: ;
-    else
-# endif
-      {
-        /* Did not find it in the table.  */
-        /* On Mac OS X, all modern locales use the UTF-8 encoding.
-           BeOS and Haiku have a single locale, and it has UTF-8 encoding.  */
-# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
-        codeset = "UTF-8";
-# else
-        /* The canonical name cannot be determined.  */
-        /* Don't return an empty string.  GNU libc and GNU libiconv interpret
-           the empty string as denoting "the locale's character encoding",
-           thus GNU libiconv would call this function a second time.  */
-        codeset = "ASCII";
-# endif
-      }
-  }
 
-#endif
+  /* Don't return an empty string.  GNU libc and GNU libiconv interpret
+     the empty string as denoting "the locale's character encoding",
+     thus GNU libiconv would call this function a second time.  */
+  if (codeset[0] == '\0')
+    codeset = "ASCII";
 
 #ifdef DARWIN7
   /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8"