"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.4/intl/localcharset.c" (3 May 2017, 6905 Bytes) of package /linux/misc/tin-2.4.4.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Determine a canonical name for the current locale's character encoding.
    2 
    3    Copyright (C) 2000-2001 Free Software Foundation, Inc.
    4 
    5    This program is free software; you can redistribute it and/or modify it
    6    under the terms of the GNU Library General Public License as published
    7    by the Free Software Foundation; either version 2, or (at your option)
    8    any later version.
    9 
   10    This program is distributed in the hope that it will be useful,
   11    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13    Library General Public License for more details.
   14 
   15    You should have received a copy of the GNU Library General Public
   16    License along with this program; if not, write to the Free Software
   17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   18    USA.  */
   19 
   20 /* Written by Bruno Haible <haible@clisp.cons.org>.  */
   21 
   22 #ifdef HAVE_CONFIG_H
   23 # include <autoconf.h>
   24 #endif
   25 
   26 #if HAVE_STDDEF_H
   27 # include <stddef.h>
   28 #endif
   29 
   30 #include <stdio.h>
   31 #if HAVE_STRING_H
   32 # include <string.h>
   33 #else
   34 # include <strings.h>
   35 #endif
   36 #if HAVE_STDLIB_H
   37 # include <stdlib.h>
   38 #endif
   39 
   40 #if defined _WIN32 || defined __WIN32__
   41 # undef WIN32   /* avoid warning on mingw32 */
   42 # define WIN32
   43 #endif
   44 
   45 #ifndef WIN32
   46 # if HAVE_LANGINFO_CODESET
   47 #  include <langinfo.h>
   48 # else
   49 #  if HAVE_SETLOCALE
   50 #   include <locale.h>
   51 #  endif
   52 # endif
   53 #else /* WIN32 */
   54 # define WIN32_LEAN_AND_MEAN
   55 # include <windows.h>
   56 #endif
   57 
   58 #ifndef DIRECTORY_SEPARATOR
   59 # define DIRECTORY_SEPARATOR '/'
   60 #endif
   61 
   62 #ifndef ISSLASH
   63 # define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
   64 #endif
   65 
   66 /* The following static variable is declared 'volatile' to avoid a
   67    possible multithread problem in the function get_charset_aliases. If we
   68    are running in a threaded environment, and if two threads initialize
   69    'charset_aliases' simultaneously, both will produce the same value,
   70    and everything will be ok if the two assignments to 'charset_aliases'
   71    are atomic. But I don't know what will happen if the two assignments mix.  */
   72 #if __STDC__ != 1
   73 # define volatile /* empty */
   74 #endif
   75 /* Pointer to the contents of the charset.alias file, if it has already been
   76    read, else NULL.  Its format is:
   77    ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
   78 static const char * volatile charset_aliases;
   79 
   80 /* Return a pointer to the contents of the charset.alias file.  */
   81 static const char *
   82 get_charset_aliases (void)
   83 {
   84   const char *cp;
   85 
   86   cp = charset_aliases;
   87   if (cp == NULL)
   88     {
   89 #ifndef WIN32
   90       FILE *fp;
   91       const char *dir = LIBDIR;
   92       const char *base = "charset.alias";
   93       char *file_name;
   94 
   95       /* Concatenate dir and base into freshly allocated file_name.  */
   96       {
   97     size_t dir_len = strlen (dir);
   98     size_t base_len = strlen (base);
   99     int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
  100     file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
  101     if (file_name != NULL)
  102       {
  103         memcpy (file_name, dir, dir_len);
  104         if (add_slash)
  105           file_name[dir_len] = DIRECTORY_SEPARATOR;
  106         memcpy (file_name + dir_len + add_slash, base, base_len + 1);
  107       }
  108       }
  109 
  110       if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
  111     /* Out of memory or file not found, treat it as empty.  */
  112     cp = "";
  113       else
  114     {
  115       /* Parse the file's contents.  */
  116       int c;
  117       char buf1[50+1];
  118       char buf2[50+1];
  119       char *res_ptr = NULL;
  120       size_t res_size = 0;
  121       size_t l1, l2;
  122 
  123       for (;;)
  124         {
  125           c = getc (fp);
  126           if (c == EOF)
  127         break;
  128           if (c == '\n' || c == ' ' || c == '\t')
  129         continue;
  130           if (c == '#')
  131         {
  132           /* Skip comment, to end of line.  */
  133           do
  134             c = getc (fp);
  135           while (!(c == EOF || c == '\n'));
  136           if (c == EOF)
  137             break;
  138           continue;
  139         }
  140           ungetc (c, fp);
  141           if (fscanf(fp, "%50s %50s", buf1, buf2) < 2)
  142         break;
  143           l1 = strlen (buf1);
  144           l2 = strlen (buf2);
  145           if (res_size == 0)
  146         {
  147           res_size = l1 + 1 + l2 + 1;
  148           res_ptr = malloc (res_size + 1);
  149         }
  150           else
  151         {
  152           res_size += l1 + 1 + l2 + 1;
  153           res_ptr = realloc (res_ptr, res_size + 1);
  154         }
  155           if (res_ptr == NULL)
  156         {
  157           /* Out of memory. */
  158           res_size = 0;
  159           break;
  160         }
  161           strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
  162           strcpy (res_ptr + res_size - (l2 + 1), buf2);
  163         }
  164       fclose (fp);
  165       if (res_size == 0)
  166         cp = "";
  167       else
  168         {
  169           *(res_ptr + res_size) = '\0';
  170           cp = res_ptr;
  171         }
  172     }
  173 
  174       if (file_name != NULL)
  175     free (file_name);
  176 
  177 #else /* WIN32 */
  178 
  179       /* To avoid the troubles of installing a separate file in the same
  180      directory as the DLL and of retrieving the DLL's directory at
  181      runtime, simply inline the aliases here.  */
  182 
  183       cp = "CP936" "\0" "GBK" "\0"
  184        "CP1361" "\0" "JOHAB" "\0";
  185 #endif
  186 
  187       charset_aliases = cp;
  188     }
  189 
  190   return cp;
  191 }
  192 
  193 /* Determine the current locale's character encoding, and canonicalize it
  194    into one of the canonical names listed in config.charset.
  195    The result must not be freed; it is statically allocated.
  196    If the canonical name cannot be determined, the result is a non-canonical
  197    name.  */
  198 
  199 #ifdef STATIC
  200 STATIC
  201 #endif
  202 const char *
  203 locale_charset (void)
  204 {
  205   const char *codeset;
  206   const char *aliases;
  207 
  208 #ifndef WIN32
  209 
  210 # if HAVE_LANGINFO_CODESET
  211 
  212   /* Most systems support nl_langinfo (CODESET) nowadays.  */
  213   codeset = nl_langinfo (CODESET);
  214 
  215 # else
  216 
  217   /* On old systems which lack it, use setlocale or getenv.  */
  218   const char *locale = NULL;
  219 
  220   /* But most old systems don't have a complete set of locales.  Some
  221      (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
  222      use setlocale here; it would return "C" when it doesn't support the
  223      locale name the user has set.  */
  224 #  if HAVE_SETLOCALE && 0
  225   locale = setlocale (LC_CTYPE, NULL);
  226 #  endif
  227   if (locale == NULL || locale[0] == '\0')
  228     {
  229       locale = getenv ("LC_ALL");
  230       if (locale == NULL || locale[0] == '\0')
  231     {
  232       locale = getenv ("LC_CTYPE");
  233       if (locale == NULL || locale[0] == '\0')
  234         locale = getenv ("LANG");
  235     }
  236     }
  237 
  238   /* On some old systems, one used to set locale = "iso8859_1". On others,
  239      you set it to "language_COUNTRY.charset". In any case, we resolve it
  240      through the charset.alias file.  */
  241   codeset = locale;
  242 
  243 # endif
  244 
  245 #else /* WIN32 */
  246 
  247   static char buf[2 + 10 + 1];
  248 
  249   /* Win32 has a function returning the locale's codepage as a number.  */
  250   sprintf (buf, "CP%u", GetACP ());
  251   codeset = buf;
  252 
  253 #endif
  254 
  255   if (codeset == NULL)
  256     /* The canonical name cannot be determined.  */
  257     codeset = "";
  258 
  259   /* Resolve alias. */
  260   for (aliases = get_charset_aliases ();
  261        *aliases != '\0';
  262        aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
  263     if (strcmp (codeset, aliases) == 0
  264     || (aliases[0] == '*' && aliases[1] == '\0'))
  265       {
  266     codeset = aliases + strlen (aliases) + 1;
  267     break;
  268       }
  269 
  270   return codeset;
  271 }