|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* -*- c-file-style: "gnu" -*- */ 00002 /* 00003 * This is a quick-and-dirty emulator of the nl_langinfo(CODESET) 00004 * function defined in the Single Unix Specification for those systems 00005 * (FreeBSD, etc.) that don't have one yet. It behaves as if it had 00006 * been called after setlocale(LC_CTYPE, ""), that is it looks at 00007 * the locale environment variables. 00008 * 00009 * http://www.opengroup.org/onlinepubs/7908799/xsh/langinfo.h.html 00010 * 00011 * Please extend it as needed and suggest improvements to the author. 00012 * This emulator will hopefully become redundant soon as 00013 * nl_langinfo(CODESET) becomes more widely implemented. 00014 * 00015 * Since the proposed Li18nux encoding name registry is still not mature, 00016 * the output follows the MIME registry where possible: 00017 * 00018 * http://www.iana.org/assignments/character-sets 00019 * 00020 * A possible autoconf test for the availability of nl_langinfo(CODESET) 00021 * can be found in 00022 * 00023 * http://www.cl.cam.ac.uk/~mgk25/unicode.html#activate 00024 * 00025 * Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11 00026 * Permission to use, copy, modify, and distribute this software 00027 * for any purpose and without fee is hereby granted. The author 00028 * disclaims all warranties with regard to this software. 00029 * 00030 * Latest version: 00031 * 00032 * http://www.cl.cam.ac.uk/~mgk25/ucs/langinfo.c 00033 */ 00034 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #if defined _WIN32 || defined __CYGWIN__ 00038 #include <windows.h> 00039 #if defined _WIN32 00040 #define strncasecmp strnicmp 00041 #endif 00042 #endif 00043 #ifdef HAVE_LANGINFO_H 00044 #include "langinfo.h" 00045 #endif 00046 00047 #define C_CODESET "US-ASCII" /* Return this as the encoding of the 00048 * C/POSIX locale. Could as well one day 00049 * become "UTF-8". */ 00050 00051 #if defined _WIN32 || defined __CYGWIN__ 00052 #define JA_CODESET "Windows-31J" 00053 #else 00054 #define JA_CODESET "EUC-JP" 00055 #endif 00056 00057 #define digit(x) ((x) >= '0' && (x) <= '9') 00058 #define strstart(s, n) (strncasecmp(s, n, strlen(n)) == 0) 00059 00060 static char buf[16]; 00061 00062 const char * 00063 nl_langinfo_codeset(void) 00064 { 00065 const char *l, *p; 00066 int n; 00067 00068 if (((l = getenv("LC_ALL")) && *l) || 00069 ((l = getenv("LC_CTYPE")) && *l) || 00070 ((l = getenv("LANG")) && *l)) { 00071 /* check standardized locales */ 00072 if (!strcmp(l, "C") || !strcmp(l, "POSIX")) 00073 return C_CODESET; 00074 /* check for encoding name fragment */ 00075 p = strchr(l, '.'); 00076 if (!p++) p = l; 00077 if (strstart(p, "UTF")) 00078 return "UTF-8"; 00079 if ((n = 5, strstart(p, "8859-")) || (n = 9, strstart(p, "ISO-8859-"))) { 00080 if (digit(p[n])) { 00081 p += n; 00082 memcpy(buf, "ISO-8859-\0\0", 12); 00083 buf[9] = *p++; 00084 if (digit(*p)) buf[10] = *p++; 00085 return buf; 00086 } 00087 } 00088 if (strstart(p, "KOI8-R")) return "KOI8-R"; 00089 if (strstart(p, "KOI8-U")) return "KOI8-U"; 00090 if (strstart(p, "620")) return "TIS-620"; 00091 if (strstart(p, "2312")) return "GB2312"; 00092 if (strstart(p, "HKSCS")) return "Big5HKSCS"; /* no MIME charset */ 00093 if (strstart(p, "BIG5")) return "Big5"; 00094 if (strstart(p, "GBK")) return "GBK"; /* no MIME charset */ 00095 if (strstart(p, "18030")) return "GB18030"; /* no MIME charset */ 00096 if (strstart(p, "Shift_JIS") || strstart(p, "SJIS")) return "Windows-31J"; 00097 /* check for conclusive modifier */ 00098 if (strstart(p, "euro")) return "ISO-8859-15"; 00099 /* check for language (and perhaps country) codes */ 00100 if (strstart(l, "zh_TW")) return "Big5"; 00101 if (strstart(l, "zh_HK")) return "Big5HKSCS"; /* no MIME charset */ 00102 if (strstart(l, "zh")) return "GB2312"; 00103 if (strstart(l, "ja")) return JA_CODESET; 00104 if (strstart(l, "ko")) return "EUC-KR"; 00105 if (strstart(l, "ru")) return "KOI8-R"; 00106 if (strstart(l, "uk")) return "KOI8-U"; 00107 if (strstart(l, "pl") || strstart(l, "hr") || 00108 strstart(l, "hu") || strstart(l, "cs") || 00109 strstart(l, "sk") || strstart(l, "sl")) return "ISO-8859-2"; 00110 if (strstart(l, "eo") || strstart(l, "mt")) return "ISO-8859-3"; 00111 if (strstart(l, "el")) return "ISO-8859-7"; 00112 if (strstart(l, "he")) return "ISO-8859-8"; 00113 if (strstart(l, "tr")) return "ISO-8859-9"; 00114 if (strstart(l, "th")) return "TIS-620"; /* or ISO-8859-11 */ 00115 if (strstart(l, "lt")) return "ISO-8859-13"; 00116 if (strstart(l, "cy")) return "ISO-8859-14"; 00117 if (strstart(l, "ro")) return "ISO-8859-2"; /* or ISO-8859-16 */ 00118 if (strstart(l, "am") || strstart(l, "vi")) return "UTF-8"; 00119 /* Send me further rules if you like, but don't forget that we are 00120 * *only* interested in locale naming conventions on platforms 00121 * that do not already provide an nl_langinfo(CODESET) implementation. */ 00122 } 00123 return NULL; 00124 } 00125 00126 #ifdef HAVE_LANGINFO_H 00127 char *nl_langinfo(nl_item item) 00128 { 00129 const char *codeset; 00130 if (item != CODESET) 00131 return NULL; 00132 codeset = nl_langinfo_codeset(); 00133 if (!codeset) codeset = C_CODESET; 00134 return (char *)codeset; 00135 } 00136 #endif 00137 00138 /* For a demo, compile with "gcc -W -Wall -o langinfo -D TEST langinfo.c" */ 00139 00140 #ifdef TEST 00141 #include <stdio.h> 00142 int main() 00143 { 00144 printf("%s\n", nl_langinfo(CODESET)); 00145 return 0; 00146 } 00147 #endif 00148
1.7.3