00001 /* nls.c -- skeletal internationalization code. */ 00002 00003 /* Copyright (C) 1996 Free Software Foundation, Inc. 00004 00005 This file is part of the GNU Readline Library, a library for 00006 reading lines of text with interactive input and history editing. 00007 00008 The GNU Readline Library is free software; you can redistribute it 00009 and/or modify it under the terms of the GNU General Public License 00010 as published by the Free Software Foundation; either version 2, or 00011 (at your option) any later version. 00012 00013 The GNU Readline Library is distributed in the hope that it will be 00014 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00015 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 The GNU General Public License is often shipped with GNU software, and 00019 is generally kept in a file called COPYING or LICENSE. If you do not 00020 have a copy of the license, write to the Free Software Foundation, 00021 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 00022 #define READLINE_LIBRARY 00023 00024 #include "config_readline.h" 00025 00026 #include <sys/types.h> 00027 00028 #include <stdio.h> 00029 00030 #if defined (HAVE_UNISTD_H) 00031 # include <unistd.h> 00032 #endif /* HAVE_UNISTD_H */ 00033 00034 #if defined (HAVE_STDLIB_H) 00035 # include <stdlib.h> 00036 #else 00037 # include "ansi_stdlib.h" 00038 #endif /* HAVE_STDLIB_H */ 00039 00040 #if defined (HAVE_LOCALE_H) 00041 # include <locale.h> 00042 #endif 00043 00044 #include <ctype.h> 00045 00046 #include "rldefs.h" 00047 #include "readline.h" 00048 #include "rlshell.h" 00049 #include "rlprivate.h" 00050 00051 #if !defined (HAVE_SETLOCALE) 00052 /* A list of legal values for the LANG or LC_CTYPE environment variables. 00053 If a locale name in this list is the value for the LC_ALL, LC_CTYPE, 00054 or LANG environment variable (using the first of those with a value), 00055 readline eight-bit mode is enabled. */ 00056 static char *legal_lang_values[] = 00057 { 00058 "iso88591", 00059 "iso88592", 00060 "iso88593", 00061 "iso88594", 00062 "iso88595", 00063 "iso88596", 00064 "iso88597", 00065 "iso88598", 00066 "iso88599", 00067 "iso885910", 00068 "koi8r", 00069 0 00070 }; 00071 00072 static char *normalize_codeset PARAMS((char *)); 00073 static char *find_codeset PARAMS((char *, size_t *)); 00074 #endif /* !HAVE_SETLOCALE */ 00075 00076 static char *_rl_get_locale_var PARAMS((const char *)); 00077 00078 static char * 00079 _rl_get_locale_var (v) 00080 const char *v; 00081 { 00082 char *lspec; 00083 00084 lspec = sh_get_env_value ("LC_ALL"); 00085 if (lspec == 0 || *lspec == 0) 00086 lspec = sh_get_env_value (v); 00087 if (lspec == 0 || *lspec == 0) 00088 lspec = sh_get_env_value ("LANG"); 00089 00090 return lspec; 00091 } 00092 00093 /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value 00094 to decide the defaults for 8-bit character input and output. Returns 00095 1 if we set eight-bit mode. */ 00096 int 00097 _rl_init_eightbit () 00098 { 00099 /* If we have setlocale(3), just check the current LC_CTYPE category 00100 value, and go into eight-bit mode if it's not C or POSIX. */ 00101 #if defined (HAVE_SETLOCALE) 00102 char *lspec, *t; 00103 00104 /* Set the LC_CTYPE locale category from environment variables. */ 00105 lspec = _rl_get_locale_var ("LC_CTYPE"); 00106 /* Since _rl_get_locale_var queries the right environment variables, 00107 we query the current locale settings with setlocale(), and, if 00108 that doesn't return anything, we set lspec to the empty string to 00109 force the subsequent call to setlocale() to define the `native' 00110 environment. */ 00111 if (lspec == 0 || *lspec == 0) 00112 lspec = setlocale (LC_CTYPE, (char *)NULL); 00113 if (lspec == 0) 00114 lspec = ""; 00115 t = setlocale (LC_CTYPE, lspec); 00116 00117 if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) 00118 { 00119 _rl_meta_flag = 1; 00120 _rl_convert_meta_chars_to_ascii = 0; 00121 _rl_output_meta_chars = 1; 00122 return (1); 00123 } 00124 else 00125 return (0); 00126 00127 #else /* !HAVE_SETLOCALE */ 00128 char *lspec, *t; 00129 int i; 00130 00131 /* We don't have setlocale. Finesse it. Check the environment for the 00132 appropriate variables and set eight-bit mode if they have the right 00133 values. */ 00134 lspec = _rl_get_locale_var ("LC_CTYPE"); 00135 00136 if (lspec == 0 || (t = normalize_codeset (lspec)) == 0) 00137 return (0); 00138 for (i = 0; t && legal_lang_values[i]; i++) 00139 if (STREQ (t, legal_lang_values[i])) 00140 { 00141 _rl_meta_flag = 1; 00142 _rl_convert_meta_chars_to_ascii = 0; 00143 _rl_output_meta_chars = 1; 00144 break; 00145 } 00146 free (t); 00147 return (legal_lang_values[i] ? 1 : 0); 00148 00149 #endif /* !HAVE_SETLOCALE */ 00150 } 00151 00152 #if !defined (HAVE_SETLOCALE) 00153 static char * 00154 normalize_codeset (codeset) 00155 char *codeset; 00156 { 00157 size_t namelen, i; 00158 int len, all_digits; 00159 char *wp, *retval; 00160 00161 codeset = find_codeset (codeset, &namelen); 00162 00163 if (codeset == 0) 00164 return (codeset); 00165 00166 all_digits = 1; 00167 for (len = 0, i = 0; i < namelen; i++) 00168 { 00169 if (ISALNUM ((unsigned char)codeset[i])) 00170 { 00171 len++; 00172 all_digits &= _rl_digit_p (codeset[i]); 00173 } 00174 } 00175 00176 retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1); 00177 if (retval == 0) 00178 return ((char *)0); 00179 00180 wp = retval; 00181 /* Add `iso' to beginning of an all-digit codeset */ 00182 if (all_digits) 00183 { 00184 *wp++ = 'i'; 00185 *wp++ = 's'; 00186 *wp++ = 'o'; 00187 } 00188 00189 for (i = 0; i < namelen; i++) 00190 if (ISALPHA ((unsigned char)codeset[i])) 00191 *wp++ = _rl_to_lower (codeset[i]); 00192 else if (_rl_digit_p (codeset[i])) 00193 *wp++ = codeset[i]; 00194 *wp = '\0'; 00195 00196 return retval; 00197 } 00198 00199 /* Isolate codeset portion of locale specification. */ 00200 static char * 00201 find_codeset (name, lenp) 00202 char *name; 00203 size_t *lenp; 00204 { 00205 char *cp, *language, *result; 00206 00207 cp = language = name; 00208 result = (char *)0; 00209 00210 while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',') 00211 cp++; 00212 00213 /* This does not make sense: language has to be specified. As 00214 an exception we allow the variable to contain only the codeset 00215 name. Perhaps there are funny codeset names. */ 00216 if (language == cp) 00217 { 00218 *lenp = strlen (language); 00219 result = language; 00220 } 00221 else 00222 { 00223 /* Next is the territory. */ 00224 if (*cp == '_') 00225 do 00226 ++cp; 00227 while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_'); 00228 00229 /* Now, finally, is the codeset. */ 00230 result = cp; 00231 if (*cp == '.') 00232 do 00233 ++cp; 00234 while (*cp && *cp != '@'); 00235 00236 if (cp - result > 2) 00237 { 00238 result++; 00239 *lenp = cp - result; 00240 } 00241 else 00242 { 00243 *lenp = strlen (language); 00244 result = language; 00245 } 00246 } 00247 00248 return result; 00249 } 00250 #endif /* !HAVE_SETLOCALE */
1.4.7

