Import readline 8.0
[deliverable/binutils-gdb.git] / readline / nls.c
CommitLineData
d60d9f65
SS
1/* nls.c -- skeletal internationalization code. */
2
cb41b9e7 3/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
d60d9f65 4
cc88a640
JK
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.
d60d9f65 7
cc88a640
JK
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
d60d9f65
SS
11 (at your option) any later version.
12
cc88a640
JK
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
d60d9f65
SS
16 GNU General Public License for more details.
17
cc88a640
JK
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
d60d9f65
SS
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
28#include <sys/types.h>
29
1b17e766
EZ
30#include <stdio.h>
31
d60d9f65
SS
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
775e241e
TT
46#if defined (HAVE_LANGINFO_CODESET)
47# include <langinfo.h>
48#endif
49
d60d9f65
SS
50#include <ctype.h>
51
52#include "rldefs.h"
1b17e766
EZ
53#include "readline.h"
54#include "rlshell.h"
55#include "rlprivate.h"
d60d9f65 56
775e241e
TT
57static int utf8locale PARAMS((char *));
58
d60d9f65
SS
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. */
64static 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",
cb41b9e7 77 "utf8",
d60d9f65
SS
78 0
79};
80
9255ee31 81static char *normalize_codeset PARAMS((char *));
5836a818 82#endif /* !HAVE_SETLOCALE */
4a11f206 83
775e241e
TT
84static char *find_codeset PARAMS((char *, size_t *));
85
5bdf8622
DJ
86static char *_rl_get_locale_var PARAMS((const char *));
87
88static char *
cb41b9e7 89_rl_get_locale_var (const char *v)
5bdf8622
DJ
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}
775e241e
TT
101
102static int
cb41b9e7 103utf8locale (char *lspec)
775e241e
TT
104{
105 char *cp;
106 size_t len;
107
108#if HAVE_LANGINFO_CODESET
109 cp = nl_langinfo (CODESET);
110 return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
111#else
112 cp = find_codeset (lspec, &len);
113
114 if (cp == 0 || len < 4 || len > 5)
115 return 0;
116 return ((len == 5) ? strncmp (cp, "UTF-8", len) == 0 : strncmp (cp, "utf8", 4) == 0);
117#endif
118}
119
cb41b9e7
TT
120/* Query the right environment variables and call setlocale() to initialize
121 the C library locale settings. */
122char *
123_rl_init_locale (void)
d60d9f65 124{
cb41b9e7 125 char *ret, *lspec;
d60d9f65
SS
126
127 /* Set the LC_CTYPE locale category from environment variables. */
5bdf8622
DJ
128 lspec = _rl_get_locale_var ("LC_CTYPE");
129 /* Since _rl_get_locale_var queries the right environment variables,
130 we query the current locale settings with setlocale(), and, if
131 that doesn't return anything, we set lspec to the empty string to
132 force the subsequent call to setlocale() to define the `native'
133 environment. */
134 if (lspec == 0 || *lspec == 0)
135 lspec = setlocale (LC_CTYPE, (char *)NULL);
136 if (lspec == 0)
137 lspec = "";
cb41b9e7
TT
138 ret = setlocale (LC_CTYPE, lspec); /* ok, since it does not change locale */
139
140 _rl_utf8locale = (ret && *ret) ? utf8locale (ret) : 0;
141
142 return ret;
143}
144
145/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
146 to decide the defaults for 8-bit character input and output. Returns
147 1 if we set eight-bit mode. */
148int
149_rl_init_eightbit (void)
150{
151/* If we have setlocale(3), just check the current LC_CTYPE category
152 value, and go into eight-bit mode if it's not C or POSIX. */
153#if defined (HAVE_SETLOCALE)
154 char *lspec, *t;
5bdf8622 155
cb41b9e7 156 t = _rl_init_locale (); /* returns static pointer */
775e241e 157
d60d9f65
SS
158 if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
159 {
160 _rl_meta_flag = 1;
161 _rl_convert_meta_chars_to_ascii = 0;
162 _rl_output_meta_chars = 1;
163 return (1);
164 }
165 else
166 return (0);
167
168#else /* !HAVE_SETLOCALE */
169 char *lspec, *t;
170 int i;
171
172 /* We don't have setlocale. Finesse it. Check the environment for the
173 appropriate variables and set eight-bit mode if they have the right
174 values. */
5bdf8622
DJ
175 lspec = _rl_get_locale_var ("LC_CTYPE");
176
d60d9f65
SS
177 if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
178 return (0);
179 for (i = 0; t && legal_lang_values[i]; i++)
180 if (STREQ (t, legal_lang_values[i]))
181 {
182 _rl_meta_flag = 1;
183 _rl_convert_meta_chars_to_ascii = 0;
184 _rl_output_meta_chars = 1;
185 break;
186 }
cb41b9e7
TT
187
188 _rl_utf8locale = *t ? STREQ (t, "utf8") : 0;
189
cc88a640 190 xfree (t);
d60d9f65 191 return (legal_lang_values[i] ? 1 : 0);
d60d9f65
SS
192#endif /* !HAVE_SETLOCALE */
193}
194
195#if !defined (HAVE_SETLOCALE)
196static char *
cb41b9e7 197normalize_codeset (char *codeset)
d60d9f65
SS
198{
199 size_t namelen, i;
200 int len, all_digits;
201 char *wp, *retval;
202
203 codeset = find_codeset (codeset, &namelen);
204
205 if (codeset == 0)
206 return (codeset);
207
208 all_digits = 1;
209 for (len = 0, i = 0; i < namelen; i++)
210 {
9255ee31 211 if (ISALNUM ((unsigned char)codeset[i]))
d60d9f65
SS
212 {
213 len++;
9255ee31 214 all_digits &= _rl_digit_p (codeset[i]);
d60d9f65
SS
215 }
216 }
217
218 retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
219 if (retval == 0)
220 return ((char *)0);
221
222 wp = retval;
223 /* Add `iso' to beginning of an all-digit codeset */
224 if (all_digits)
225 {
226 *wp++ = 'i';
227 *wp++ = 's';
228 *wp++ = 'o';
229 }
230
231 for (i = 0; i < namelen; i++)
9255ee31
EZ
232 if (ISALPHA ((unsigned char)codeset[i]))
233 *wp++ = _rl_to_lower (codeset[i]);
234 else if (_rl_digit_p (codeset[i]))
d60d9f65
SS
235 *wp++ = codeset[i];
236 *wp = '\0';
237
238 return retval;
239}
775e241e 240#endif /* !HAVE_SETLOCALE */
d60d9f65
SS
241
242/* Isolate codeset portion of locale specification. */
243static char *
cb41b9e7 244find_codeset (char *name, size_t *lenp)
d60d9f65
SS
245{
246 char *cp, *language, *result;
247
248 cp = language = name;
249 result = (char *)0;
250
251 while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
252 cp++;
253
254 /* This does not make sense: language has to be specified. As
255 an exception we allow the variable to contain only the codeset
256 name. Perhaps there are funny codeset names. */
257 if (language == cp)
258 {
259 *lenp = strlen (language);
260 result = language;
261 }
262 else
263 {
264 /* Next is the territory. */
265 if (*cp == '_')
266 do
267 ++cp;
268 while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
269
270 /* Now, finally, is the codeset. */
271 result = cp;
272 if (*cp == '.')
273 do
274 ++cp;
275 while (*cp && *cp != '@');
276
277 if (cp - result > 2)
278 {
279 result++;
280 *lenp = cp - result;
281 }
282 else
283 {
284 *lenp = strlen (language);
285 result = language;
286 }
287 }
288
289 return result;
290}
This page took 1.149609 seconds and 4 git commands to generate.