|
|
| version 1.1, 2012/02/21 22:57:48 | version 1.1.1.2, 2012/05/29 09:29:42 |
|---|---|
| Line 1 | Line 1 |
| /* Determine a canonical name for the current locale's character encoding. | /* Determine a canonical name for the current locale's character encoding. |
| Copyright (C) 2000-2006, 2008-2009 Free Software Foundation, Inc. | Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, Inc. |
| This program is free software; you can redistribute it and/or modify it | This program is free software; you can redistribute it and/or modify it |
| under the terms of the GNU Library General Public License as published | under the terms of the GNU Library General Public License as published |
| Line 24 | Line 24 |
| /* Specification. */ | /* Specification. */ |
| #include "localcharset.h" | #include "localcharset.h" |
| #include <fcntl.h> | |
| #include <stddef.h> | #include <stddef.h> |
| #include <stdio.h> | #include <stdio.h> |
| #include <string.h> | #include <string.h> |
| Line 45 | Line 46 |
| #endif | #endif |
| #if !defined WIN32_NATIVE | #if !defined WIN32_NATIVE |
| # include <unistd.h> | |
| # if HAVE_LANGINFO_CODESET | # if HAVE_LANGINFO_CODESET |
| # include <langinfo.h> | # include <langinfo.h> |
| # else | # else |
| Line 76 | Line 78 |
| # include "configmake.h" | # include "configmake.h" |
| #endif | #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__ | #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ |
| /* Win32, Cygwin, OS/2, DOS */ | /* Win32, Cygwin, OS/2, DOS */ |
| # define ISSLASH(C) ((C) == '/' || (C) == '\\') | # define ISSLASH(C) ((C) == '/' || (C) == '\\') |
| Line 118 get_charset_aliases (void) | Line 125 get_charset_aliases (void) |
| if (cp == NULL) | if (cp == NULL) |
| { | { |
| #if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) | #if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) |
| FILE *fp; | |
| const char *dir; | const char *dir; |
| const char *base = "charset.alias"; | const char *base = "charset.alias"; |
| char *file_name; | char *file_name; |
| /* Make it possible to override the charset.alias location. This is | /* Make it possible to override the charset.alias location. This is |
| necessary for running the testsuite before "make install". */ | necessary for running the testsuite before "make install". */ |
| dir = getenv ("CHARSETALIASDIR"); | dir = getenv ("CHARSETALIASDIR"); |
| if (dir == NULL || dir[0] == '\0') | if (dir == NULL || dir[0] == '\0') |
| dir = relocate (LIBDIR); | dir = relocate (LIBDIR); |
| /* Concatenate dir and base into freshly allocated file_name. */ | /* Concatenate dir and base into freshly allocated file_name. */ |
| { | { |
| size_t dir_len = strlen (dir); | size_t dir_len = strlen (dir); |
| size_t base_len = strlen (base); | size_t base_len = strlen (base); |
| int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); | int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); |
| file_name = (char *) malloc (dir_len + add_slash + base_len + 1); | file_name = (char *) malloc (dir_len + add_slash + base_len + 1); |
| if (file_name != NULL) | if (file_name != NULL) |
| { | { |
| memcpy (file_name, dir, dir_len); | memcpy (file_name, dir, dir_len); |
| if (add_slash) | if (add_slash) |
| file_name[dir_len] = DIRECTORY_SEPARATOR; | file_name[dir_len] = DIRECTORY_SEPARATOR; |
| memcpy (file_name + dir_len + add_slash, base, base_len + 1); | memcpy (file_name + dir_len + add_slash, base, base_len + 1); |
| } | } |
| } | } |
| if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) | if (file_name == NULL) |
| /* Out of memory or file not found, treat it as empty. */ | /* Out of memory. Treat the file as empty. */ |
| cp = ""; | cp = ""; |
| else | else |
| { | { |
| /* Parse the file's contents. */ | int fd; |
| char *res_ptr = NULL; | |
| size_t res_size = 0; | |
| for (;;) | /* Open the file. Reject symbolic links on platforms that support |
| { | O_NOFOLLOW. This is a security feature. Without it, an attacker |
| int c; | could retrieve parts of the contents (namely, the tail of the |
| char buf1[50+1]; | first line that starts with "* ") of an arbitrary file by placing |
| char buf2[50+1]; | a symbolic link to that file under the name "charset.alias" in |
| size_t l1, l2; | some writable directory and defining the environment variable |
| char *old_res_ptr; | 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; | |
| c = getc (fp); | fp = fdopen (fd, "r"); |
| if (c == EOF) | if (fp == NULL) |
| break; | { |
| if (c == '\n' || c == ' ' || c == '\t') | /* Out of memory. Treat the file as empty. */ |
| continue; | close (fd); |
| if (c == '#') | cp = ""; |
| { | } |
| /* Skip comment, to end of line. */ | else |
| do | { |
| c = getc (fp); | /* Parse the file's contents. */ |
| while (!(c == EOF || c == '\n')); | char *res_ptr = NULL; |
| if (c == EOF) | size_t res_size = 0; |
| 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; | |
| if (old_res_ptr != NULL) | |
| 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; | |
| } | |
| } | |
| if (file_name != NULL) | for (;;) |
| free (file_name); | { |
| 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 | #else |
| # if defined DARWIN7 | # if defined DARWIN7 |
| /* To avoid the trouble of installing a file that is shared by many | /* To avoid the trouble of installing a file that is shared by many |
| GNU packages -- many packaging systems have problems with this --, | GNU packages -- many packaging systems have problems with this --, |
| simply inline the aliases here. */ | simply inline the aliases here. */ |
| cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" | cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" |
| "ISO8859-2" "\0" "ISO-8859-2" "\0" | "ISO8859-2" "\0" "ISO-8859-2" "\0" |
| "ISO8859-4" "\0" "ISO-8859-4" "\0" | "ISO8859-4" "\0" "ISO-8859-4" "\0" |
| "ISO8859-5" "\0" "ISO-8859-5" "\0" | "ISO8859-5" "\0" "ISO-8859-5" "\0" |
| "ISO8859-7" "\0" "ISO-8859-7" "\0" | "ISO8859-7" "\0" "ISO-8859-7" "\0" |
| "ISO8859-9" "\0" "ISO-8859-9" "\0" | "ISO8859-9" "\0" "ISO-8859-9" "\0" |
| "ISO8859-13" "\0" "ISO-8859-13" "\0" | "ISO8859-13" "\0" "ISO-8859-13" "\0" |
| "ISO8859-15" "\0" "ISO-8859-15" "\0" | "ISO8859-15" "\0" "ISO-8859-15" "\0" |
| "KOI8-R" "\0" "KOI8-R" "\0" | "KOI8-R" "\0" "KOI8-R" "\0" |
| "KOI8-U" "\0" "KOI8-U" "\0" | "KOI8-U" "\0" "KOI8-U" "\0" |
| "CP866" "\0" "CP866" "\0" | "CP866" "\0" "CP866" "\0" |
| "CP949" "\0" "CP949" "\0" | "CP949" "\0" "CP949" "\0" |
| "CP1131" "\0" "CP1131" "\0" | "CP1131" "\0" "CP1131" "\0" |
| "CP1251" "\0" "CP1251" "\0" | "CP1251" "\0" "CP1251" "\0" |
| "eucCN" "\0" "GB2312" "\0" | "eucCN" "\0" "GB2312" "\0" |
| "GB2312" "\0" "GB2312" "\0" | "GB2312" "\0" "GB2312" "\0" |
| "eucJP" "\0" "EUC-JP" "\0" | "eucJP" "\0" "EUC-JP" "\0" |
| "eucKR" "\0" "EUC-KR" "\0" | "eucKR" "\0" "EUC-KR" "\0" |
| "Big5" "\0" "BIG5" "\0" | "Big5" "\0" "BIG5" "\0" |
| "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" | "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" |
| "GBK" "\0" "GBK" "\0" | "GBK" "\0" "GBK" "\0" |
| "GB18030" "\0" "GB18030" "\0" | "GB18030" "\0" "GB18030" "\0" |
| "SJIS" "\0" "SHIFT_JIS" "\0" | "SJIS" "\0" "SHIFT_JIS" "\0" |
| "ARMSCII-8" "\0" "ARMSCII-8" "\0" | "ARMSCII-8" "\0" "ARMSCII-8" "\0" |
| "PT154" "\0" "PT154" "\0" | "PT154" "\0" "PT154" "\0" |
| /*"ISCII-DEV" "\0" "?" "\0"*/ | /*"ISCII-DEV" "\0" "?" "\0"*/ |
| "*" "\0" "UTF-8" "\0"; | "*" "\0" "UTF-8" "\0"; |
| # endif | # endif |
| # if defined VMS | # if defined VMS |
| /* To avoid the troubles of an extra file charset.alias_vms in the | /* To avoid the troubles of an extra file charset.alias_vms in the |
| sources of many GNU packages, simply inline the aliases here. */ | sources of many GNU packages, simply inline the aliases here. */ |
| /* The list of encodings is taken from the OpenVMS 7.3-1 documentation | /* The list of encodings is taken from the OpenVMS 7.3-1 documentation |
| "Compaq C Run-Time Library Reference Manual for OpenVMS systems" | "Compaq C Run-Time Library Reference Manual for OpenVMS systems" |
| section 10.7 "Handling Different Character Sets". */ | section 10.7 "Handling Different Character Sets". */ |
| cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" | cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" |
| "ISO8859-2" "\0" "ISO-8859-2" "\0" | "ISO8859-2" "\0" "ISO-8859-2" "\0" |
| "ISO8859-5" "\0" "ISO-8859-5" "\0" | "ISO8859-5" "\0" "ISO-8859-5" "\0" |
| "ISO8859-7" "\0" "ISO-8859-7" "\0" | "ISO8859-7" "\0" "ISO-8859-7" "\0" |
| "ISO8859-8" "\0" "ISO-8859-8" "\0" | "ISO8859-8" "\0" "ISO-8859-8" "\0" |
| "ISO8859-9" "\0" "ISO-8859-9" "\0" | "ISO8859-9" "\0" "ISO-8859-9" "\0" |
| /* Japanese */ | /* Japanese */ |
| "eucJP" "\0" "EUC-JP" "\0" | "eucJP" "\0" "EUC-JP" "\0" |
| "SJIS" "\0" "SHIFT_JIS" "\0" | "SJIS" "\0" "SHIFT_JIS" "\0" |
| "DECKANJI" "\0" "DEC-KANJI" "\0" | "DECKANJI" "\0" "DEC-KANJI" "\0" |
| "SDECKANJI" "\0" "EUC-JP" "\0" | "SDECKANJI" "\0" "EUC-JP" "\0" |
| /* Chinese */ | /* Chinese */ |
| "eucTW" "\0" "EUC-TW" "\0" | "eucTW" "\0" "EUC-TW" "\0" |
| "DECHANYU" "\0" "DEC-HANYU" "\0" | "DECHANYU" "\0" "DEC-HANYU" "\0" |
| "DECHANZI" "\0" "GB2312" "\0" | "DECHANZI" "\0" "GB2312" "\0" |
| /* Korean */ | /* Korean */ |
| "DECKOREAN" "\0" "EUC-KR" "\0"; | "DECKOREAN" "\0" "EUC-KR" "\0"; |
| # endif | # endif |
| # if defined WIN32_NATIVE || defined __CYGWIN__ | # if defined WIN32_NATIVE || defined __CYGWIN__ |
| /* To avoid the troubles of installing a separate file in the same | /* To avoid the troubles of installing a separate file in the same |
| directory as the DLL and of retrieving the DLL's directory at | directory as the DLL and of retrieving the DLL's directory at |
| runtime, simply inline the aliases here. */ | runtime, simply inline the aliases here. */ |
| cp = "CP936" "\0" "GBK" "\0" | cp = "CP936" "\0" "GBK" "\0" |
| "CP1361" "\0" "JOHAB" "\0" | "CP1361" "\0" "JOHAB" "\0" |
| "CP20127" "\0" "ASCII" "\0" | "CP20127" "\0" "ASCII" "\0" |
| "CP20866" "\0" "KOI8-R" "\0" | "CP20866" "\0" "KOI8-R" "\0" |
| "CP20936" "\0" "GB2312" "\0" | "CP20936" "\0" "GB2312" "\0" |
| "CP21866" "\0" "KOI8-RU" "\0" | "CP21866" "\0" "KOI8-RU" "\0" |
| "CP28591" "\0" "ISO-8859-1" "\0" | "CP28591" "\0" "ISO-8859-1" "\0" |
| "CP28592" "\0" "ISO-8859-2" "\0" | "CP28592" "\0" "ISO-8859-2" "\0" |
| "CP28593" "\0" "ISO-8859-3" "\0" | "CP28593" "\0" "ISO-8859-3" "\0" |
| "CP28594" "\0" "ISO-8859-4" "\0" | "CP28594" "\0" "ISO-8859-4" "\0" |
| "CP28595" "\0" "ISO-8859-5" "\0" | "CP28595" "\0" "ISO-8859-5" "\0" |
| "CP28596" "\0" "ISO-8859-6" "\0" | "CP28596" "\0" "ISO-8859-6" "\0" |
| "CP28597" "\0" "ISO-8859-7" "\0" | "CP28597" "\0" "ISO-8859-7" "\0" |
| "CP28598" "\0" "ISO-8859-8" "\0" | "CP28598" "\0" "ISO-8859-8" "\0" |
| "CP28599" "\0" "ISO-8859-9" "\0" | "CP28599" "\0" "ISO-8859-9" "\0" |
| "CP28605" "\0" "ISO-8859-15" "\0" | "CP28605" "\0" "ISO-8859-15" "\0" |
| "CP38598" "\0" "ISO-8859-8" "\0" | "CP38598" "\0" "ISO-8859-8" "\0" |
| "CP51932" "\0" "EUC-JP" "\0" | "CP51932" "\0" "EUC-JP" "\0" |
| "CP51936" "\0" "GB2312" "\0" | "CP51936" "\0" "GB2312" "\0" |
| "CP51949" "\0" "EUC-KR" "\0" | "CP51949" "\0" "EUC-KR" "\0" |
| "CP51950" "\0" "EUC-TW" "\0" | "CP51950" "\0" "EUC-TW" "\0" |
| "CP54936" "\0" "GB18030" "\0" | "CP54936" "\0" "GB18030" "\0" |
| "CP65001" "\0" "UTF-8" "\0"; | "CP65001" "\0" "UTF-8" "\0"; |
| # endif | # endif |
| #endif | #endif |
| Line 336 locale_charset (void) | Line 369 locale_charset (void) |
| codeset = nl_langinfo (CODESET); | codeset = nl_langinfo (CODESET); |
| # ifdef __CYGWIN__ | # ifdef __CYGWIN__ |
| /* Cygwin 2006 does not have locales. nl_langinfo (CODESET) always | /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always |
| returns "US-ASCII". As long as this is not fixed, return the suffix | returns "US-ASCII". Return the suffix of the locale name from the |
| of the locale name from the environment variables (if present) or | environment variables (if present) or the codepage as a number. */ |
| the codepage as a number. */ | |
| if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) | if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) |
| { | { |
| const char *locale; | const char *locale; |
| Line 347 locale_charset (void) | Line 379 locale_charset (void) |
| locale = getenv ("LC_ALL"); | locale = getenv ("LC_ALL"); |
| if (locale == NULL || locale[0] == '\0') | if (locale == NULL || locale[0] == '\0') |
| { | { |
| locale = getenv ("LC_CTYPE"); | locale = getenv ("LC_CTYPE"); |
| if (locale == NULL || locale[0] == '\0') | if (locale == NULL || locale[0] == '\0') |
| locale = getenv ("LANG"); | locale = getenv ("LANG"); |
| } | } |
| if (locale != NULL && locale[0] != '\0') | if (locale != NULL && locale[0] != '\0') |
| { | { |
| /* If the locale name contains an encoding after the dot, return | /* If the locale name contains an encoding after the dot, return |
| it. */ | it. */ |
| const char *dot = strchr (locale, '.'); | const char *dot = strchr (locale, '.'); |
| if (dot != NULL) | if (dot != NULL) |
| { | { |
| const char *modifier; | const char *modifier; |
| dot++; | dot++; |
| /* Look for the possible @... trailer and remove it, if any. */ | /* Look for the possible @... trailer and remove it, if any. */ |
| modifier = strchr (dot, '@'); | modifier = strchr (dot, '@'); |
| if (modifier == NULL) | if (modifier == NULL) |
| return dot; | return dot; |
| if (modifier - dot < sizeof (buf)) | if (modifier - dot < sizeof (buf)) |
| { | { |
| memcpy (buf, dot, modifier - dot); | memcpy (buf, dot, modifier - dot); |
| buf [modifier - dot] = '\0'; | buf [modifier - dot] = '\0'; |
| return buf; | return buf; |
| } | } |
| } | } |
| } | } |
| /* Woe32 has a function returning the locale's codepage as a number. */ | /* Woe32 has a function returning the locale's codepage as a number: |
| GetACP(). This encoding is used by Cygwin, unless the user has set | |
| the environment variable CYGWIN=codepage:oem (which very few people | |
| do). | |
| Output directed to console windows needs to be converted (to | |
| GetOEMCP() if the console is using a raster font, or to | |
| GetConsoleOutputCP() if it is using a TrueType font). Cygwin does | |
| this conversion transparently (see winsup/cygwin/fhandler_console.cc), | |
| converting to GetConsoleOutputCP(). This leads to correct results, | |
| except when SetConsoleOutputCP has been called and a raster font is | |
| in use. */ | |
| sprintf (buf, "CP%u", GetACP ()); | sprintf (buf, "CP%u", GetACP ()); |
| codeset = buf; | codeset = buf; |
| } | } |
| Line 398 locale_charset (void) | Line 440 locale_charset (void) |
| { | { |
| locale = getenv ("LC_ALL"); | locale = getenv ("LC_ALL"); |
| if (locale == NULL || locale[0] == '\0') | if (locale == NULL || locale[0] == '\0') |
| { | { |
| locale = getenv ("LC_CTYPE"); | locale = getenv ("LC_CTYPE"); |
| if (locale == NULL || locale[0] == '\0') | if (locale == NULL || locale[0] == '\0') |
| locale = getenv ("LANG"); | locale = getenv ("LANG"); |
| } | } |
| } | } |
| /* On some old systems, one used to set locale = "iso8859_1". On others, | /* On some old systems, one used to set locale = "iso8859_1". On others, |
| Line 416 locale_charset (void) | Line 458 locale_charset (void) |
| static char buf[2 + 10 + 1]; | static char buf[2 + 10 + 1]; |
| /* Woe32 has a function returning the locale's codepage as a number. */ | /* Woe32 has a function returning the locale's codepage as a number: |
| GetACP(). | |
| When the output goes to a console window, it needs to be provided in | |
| GetOEMCP() encoding if the console is using a raster font, or in | |
| GetConsoleOutputCP() encoding if it is using a TrueType font. | |
| But in GUI programs and for output sent to files and pipes, GetACP() | |
| encoding is the best bet. */ | |
| sprintf (buf, "CP%u", GetACP ()); | sprintf (buf, "CP%u", GetACP ()); |
| codeset = buf; | codeset = buf; |
| Line 434 locale_charset (void) | Line 482 locale_charset (void) |
| { | { |
| locale = getenv ("LC_CTYPE"); | locale = getenv ("LC_CTYPE"); |
| if (locale == NULL || locale[0] == '\0') | if (locale == NULL || locale[0] == '\0') |
| locale = getenv ("LANG"); | locale = getenv ("LANG"); |
| } | } |
| if (locale != NULL && locale[0] != '\0') | if (locale != NULL && locale[0] != '\0') |
| { | { |
| Line 442 locale_charset (void) | Line 490 locale_charset (void) |
| const char *dot = strchr (locale, '.'); | const char *dot = strchr (locale, '.'); |
| if (dot != NULL) | if (dot != NULL) |
| { | { |
| const char *modifier; | const char *modifier; |
| dot++; | dot++; |
| /* Look for the possible @... trailer and remove it, if any. */ | /* Look for the possible @... trailer and remove it, if any. */ |
| modifier = strchr (dot, '@'); | modifier = strchr (dot, '@'); |
| if (modifier == NULL) | if (modifier == NULL) |
| return dot; | return dot; |
| if (modifier - dot < sizeof (buf)) | if (modifier - dot < sizeof (buf)) |
| { | { |
| memcpy (buf, dot, modifier - dot); | memcpy (buf, dot, modifier - dot); |
| buf [modifier - dot] = '\0'; | buf [modifier - dot] = '\0'; |
| return buf; | return buf; |
| } | } |
| } | } |
| /* Resolve through the charset.alias file. */ | /* Resolve through the charset.alias file. */ |
| codeset = locale; | codeset = locale; |
| Line 465 locale_charset (void) | Line 513 locale_charset (void) |
| { | { |
| /* OS/2 has a function returning the locale's codepage as a number. */ | /* OS/2 has a function returning the locale's codepage as a number. */ |
| if (DosQueryCp (sizeof (cp), cp, &cplen)) | if (DosQueryCp (sizeof (cp), cp, &cplen)) |
| codeset = ""; | codeset = ""; |
| else | else |
| { | { |
| sprintf (buf, "CP%u", cp[0]); | sprintf (buf, "CP%u", cp[0]); |
| codeset = buf; | codeset = buf; |
| } | } |
| } | } |
| #endif | #endif |
| Line 484 locale_charset (void) | Line 532 locale_charset (void) |
| *aliases != '\0'; | *aliases != '\0'; |
| aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) | aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) |
| if (strcmp (codeset, aliases) == 0 | if (strcmp (codeset, aliases) == 0 |
| || (aliases[0] == '*' && aliases[1] == '\0')) | || (aliases[0] == '*' && aliases[1] == '\0')) |
| { | { |
| codeset = aliases + strlen (aliases) + 1; | codeset = aliases + strlen (aliases) + 1; |
| break; | break; |
| } | } |
| /* Don't return an empty string. GNU libc and GNU libiconv interpret | /* Don't return an empty string. GNU libc and GNU libiconv interpret |