Annotation of embedaddon/readline/nls.c, revision 1.1.1.1
1.1 misho 1: /* nls.c -- skeletal internationalization code. */
2:
3: /* Copyright (C) 1996-2009 Free Software Foundation, Inc.
4:
5: This file is part of the GNU Readline Library (Readline), a library
6: for reading lines of text with interactive input and history editing.
7:
8: Readline is free software: you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation, either version 3 of the License, or
11: (at your option) any later version.
12:
13: Readline is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with Readline. If not, see <http://www.gnu.org/licenses/>.
20: */
21:
22: #define READLINE_LIBRARY
23:
24: #if defined (HAVE_CONFIG_H)
25: # include <config.h>
26: #endif
27:
28: #include <sys/types.h>
29:
30: #include <stdio.h>
31:
32: #if defined (HAVE_UNISTD_H)
33: # include <unistd.h>
34: #endif /* HAVE_UNISTD_H */
35:
36: #if defined (HAVE_STDLIB_H)
37: # include <stdlib.h>
38: #else
39: # include "ansi_stdlib.h"
40: #endif /* HAVE_STDLIB_H */
41:
42: #if defined (HAVE_LOCALE_H)
43: # include <locale.h>
44: #endif
45:
46: #if defined (HAVE_LANGINFO_CODESET)
47: # include <langinfo.h>
48: #endif
49:
50: #include <ctype.h>
51:
52: #include "rldefs.h"
53: #include "readline.h"
54: #include "rlshell.h"
55: #include "rlprivate.h"
56:
57: static int utf8locale PARAMS((char *));
58:
59: #if !defined (HAVE_SETLOCALE)
60: /* A list of legal values for the LANG or LC_CTYPE environment variables.
61: If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
62: or LANG environment variable (using the first of those with a value),
63: readline eight-bit mode is enabled. */
64: static char *legal_lang_values[] =
65: {
66: "iso88591",
67: "iso88592",
68: "iso88593",
69: "iso88594",
70: "iso88595",
71: "iso88596",
72: "iso88597",
73: "iso88598",
74: "iso88599",
75: "iso885910",
76: "koi8r",
77: 0
78: };
79:
80: static char *normalize_codeset PARAMS((char *));
81: #endif /* !HAVE_SETLOCALE */
82:
83: static char *find_codeset PARAMS((char *, size_t *));
84:
85: static char *_rl_get_locale_var PARAMS((const char *));
86:
87: static char *
88: _rl_get_locale_var (v)
89: const char *v;
90: {
91: char *lspec;
92:
93: lspec = sh_get_env_value ("LC_ALL");
94: if (lspec == 0 || *lspec == 0)
95: lspec = sh_get_env_value (v);
96: if (lspec == 0 || *lspec == 0)
97: lspec = sh_get_env_value ("LANG");
98:
99: return lspec;
100: }
101:
102: static int
103: utf8locale (lspec)
104: char *lspec;
105: {
106: char *cp;
107: size_t len;
108:
109: #if HAVE_LANGINFO_CODESET
110: cp = nl_langinfo (CODESET);
111: return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
112: #else
113: cp = find_codeset (lspec, &len);
114:
115: if (cp == 0 || len < 4 || len > 5)
116: return 0;
117: return ((len == 5) ? strncmp (cp, "UTF-8", len) == 0 : strncmp (cp, "utf8", 4) == 0);
118: #endif
119: }
120:
121: /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
122: to decide the defaults for 8-bit character input and output. Returns
123: 1 if we set eight-bit mode. */
124: int
125: _rl_init_eightbit ()
126: {
127: /* If we have setlocale(3), just check the current LC_CTYPE category
128: value, and go into eight-bit mode if it's not C or POSIX. */
129: #if defined (HAVE_SETLOCALE)
130: char *lspec, *t;
131:
132: /* Set the LC_CTYPE locale category from environment variables. */
133: lspec = _rl_get_locale_var ("LC_CTYPE");
134: /* Since _rl_get_locale_var queries the right environment variables,
135: we query the current locale settings with setlocale(), and, if
136: that doesn't return anything, we set lspec to the empty string to
137: force the subsequent call to setlocale() to define the `native'
138: environment. */
139: if (lspec == 0 || *lspec == 0)
140: lspec = setlocale (LC_CTYPE, (char *)NULL);
141: if (lspec == 0)
142: lspec = "";
143: t = setlocale (LC_CTYPE, lspec);
144:
145: if (t && *t)
146: _rl_utf8locale = utf8locale (t);
147:
148: if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
149: {
150: _rl_meta_flag = 1;
151: _rl_convert_meta_chars_to_ascii = 0;
152: _rl_output_meta_chars = 1;
153: return (1);
154: }
155: else
156: return (0);
157:
158: #else /* !HAVE_SETLOCALE */
159: char *lspec, *t;
160: int i;
161:
162: /* We don't have setlocale. Finesse it. Check the environment for the
163: appropriate variables and set eight-bit mode if they have the right
164: values. */
165: lspec = _rl_get_locale_var ("LC_CTYPE");
166:
167: if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
168: return (0);
169: for (i = 0; t && legal_lang_values[i]; i++)
170: if (STREQ (t, legal_lang_values[i]))
171: {
172: _rl_meta_flag = 1;
173: _rl_convert_meta_chars_to_ascii = 0;
174: _rl_output_meta_chars = 1;
175: break;
176: }
177: xfree (t);
178: return (legal_lang_values[i] ? 1 : 0);
179:
180: #endif /* !HAVE_SETLOCALE */
181: }
182:
183: #if !defined (HAVE_SETLOCALE)
184: static char *
185: normalize_codeset (codeset)
186: char *codeset;
187: {
188: size_t namelen, i;
189: int len, all_digits;
190: char *wp, *retval;
191:
192: codeset = find_codeset (codeset, &namelen);
193:
194: if (codeset == 0)
195: return (codeset);
196:
197: all_digits = 1;
198: for (len = 0, i = 0; i < namelen; i++)
199: {
200: if (ISALNUM ((unsigned char)codeset[i]))
201: {
202: len++;
203: all_digits &= _rl_digit_p (codeset[i]);
204: }
205: }
206:
207: retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
208: if (retval == 0)
209: return ((char *)0);
210:
211: wp = retval;
212: /* Add `iso' to beginning of an all-digit codeset */
213: if (all_digits)
214: {
215: *wp++ = 'i';
216: *wp++ = 's';
217: *wp++ = 'o';
218: }
219:
220: for (i = 0; i < namelen; i++)
221: if (ISALPHA ((unsigned char)codeset[i]))
222: *wp++ = _rl_to_lower (codeset[i]);
223: else if (_rl_digit_p (codeset[i]))
224: *wp++ = codeset[i];
225: *wp = '\0';
226:
227: return retval;
228: }
229: #endif /* !HAVE_SETLOCALE */
230:
231: /* Isolate codeset portion of locale specification. */
232: static char *
233: find_codeset (name, lenp)
234: char *name;
235: size_t *lenp;
236: {
237: char *cp, *language, *result;
238:
239: cp = language = name;
240: result = (char *)0;
241:
242: while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
243: cp++;
244:
245: /* This does not make sense: language has to be specified. As
246: an exception we allow the variable to contain only the codeset
247: name. Perhaps there are funny codeset names. */
248: if (language == cp)
249: {
250: *lenp = strlen (language);
251: result = language;
252: }
253: else
254: {
255: /* Next is the territory. */
256: if (*cp == '_')
257: do
258: ++cp;
259: while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
260:
261: /* Now, finally, is the codeset. */
262: result = cp;
263: if (*cp == '.')
264: do
265: ++cp;
266: while (*cp && *cp != '@');
267:
268: if (cp - result > 2)
269: {
270: result++;
271: *lenp = cp - result;
272: }
273: else
274: {
275: *lenp = strlen (language);
276: result = language;
277: }
278: }
279:
280: return result;
281: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>