"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.1/intl/localcharset.c" (28 Aug 2013, 6905 Bytes) of package /linux/misc/tin-2.4.1.tar.gz:


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. For more information about "localcharset.c" see the Fossies "Dox" file reference documentation.

    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 }