]> git.ipfire.org Git - thirdparty/bash.git/blame - locale.c
commit bash-20150619 snapshot
[thirdparty/bash.git] / locale.c
CommitLineData
ccc6cda3
JA
1/* locale.c - Miscellaneous internationalization functions. */
2
863d31ae 3/* Copyright (C) 1996-2009,2012 Free Software Foundation, Inc.
ccc6cda3
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
2e4498b3
CR
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
ccc6cda3 11
2e4498b3
CR
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
ccc6cda3 16
2e4498b3
CR
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
ccc6cda3
JA
20
21#include "config.h"
22
23#include "bashtypes.h"
24
25#if defined (HAVE_UNISTD_H)
26# include <unistd.h>
27#endif
28
22818c14
CR
29#if HAVE_LANGINFO_CODESET
30# include <langinfo.h>
31#endif
32
ccc6cda3
JA
33#include "bashintl.h"
34#include "bashansi.h"
35#include <stdio.h>
f73dda09 36#include "chartypes.h"
547ef914 37#include <errno.h>
ccc6cda3
JA
38
39#include "shell.h"
7117c2d2
JA
40#include "input.h" /* For bash_input */
41
547ef914
CR
42#ifndef errno
43extern int errno;
44#endif
45
22818c14 46int locale_utf8locale; /* unused for now */
51f7ea36 47int locale_mb_cur_max; /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
22818c14 48
7117c2d2 49extern int dump_translatable_strings, dump_po_strings;
ccc6cda3
JA
50
51/* The current locale when the program begins */
52static char *default_locale;
53
54/* The current domain for textdomain(3). */
55static char *default_domain;
56static char *default_dir;
57
58/* tracks the value of LC_ALL; used to override values for other locale
59 categories */
60static char *lc_all;
61
d3a24ed2
CR
62/* tracks the value of LC_ALL; used to provide defaults for locale
63 categories */
64static char *lang;
65
43cdcad8
CR
66/* Called to reset all of the locale variables to their appropriate values
67 if (and only if) LC_ALL has not been assigned a value. */
d3a24ed2
CR
68static int reset_locale_vars __P((void));
69
70static void locale_setblanks __P((void));
22818c14 71static int locale_isutf8 __P((char *));
d3a24ed2 72
ccc6cda3
JA
73/* Set the value of default_locale and make the current locale the
74 system default locale. This should be called very early in main(). */
75void
76set_default_locale ()
77{
78#if defined (HAVE_SETLOCALE)
79 default_locale = setlocale (LC_ALL, "");
80 if (default_locale)
81 default_locale = savestring (default_locale);
82#endif /* HAVE_SETLOCALE */
5e13499c
CR
83 bindtextdomain (PACKAGE, LOCALEDIR);
84 textdomain (PACKAGE);
51f7ea36
CR
85
86 locale_mb_cur_max = MB_CUR_MAX;
ccc6cda3
JA
87}
88
898cc92e
CR
89/* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
90 LC_TIME if they are not specified in the environment, but LC_ALL is. This
ccc6cda3
JA
91 should be called from main() after parsing the environment. */
92void
93set_default_locale_vars ()
94{
95 char *val;
96
97#if defined (HAVE_SETLOCALE)
d3a24ed2
CR
98
99# if defined (LC_CTYPE)
ccc6cda3
JA
100 val = get_string_value ("LC_CTYPE");
101 if (val == 0 && lc_all && *lc_all)
d3a24ed2
CR
102 {
103 setlocale (LC_CTYPE, lc_all);
104 locale_setblanks ();
51f7ea36 105 locale_mb_cur_max = MB_CUR_MAX;
1f6ec1a8 106 u32reset ();
d3a24ed2
CR
107 }
108# endif
ccc6cda3
JA
109
110# if defined (LC_COLLATE)
111 val = get_string_value ("LC_COLLATE");
112 if (val == 0 && lc_all && *lc_all)
113 setlocale (LC_COLLATE, lc_all);
114# endif /* LC_COLLATE */
115
116# if defined (LC_MESSAGES)
117 val = get_string_value ("LC_MESSAGES");
118 if (val == 0 && lc_all && *lc_all)
119 setlocale (LC_MESSAGES, lc_all);
120# endif /* LC_MESSAGES */
121
bb70624e
JA
122# if defined (LC_NUMERIC)
123 val = get_string_value ("LC_NUMERIC");
124 if (val == 0 && lc_all && *lc_all)
125 setlocale (LC_NUMERIC, lc_all);
126# endif /* LC_NUMERIC */
127
898cc92e
CR
128# if defined (LC_TIME)
129 val = get_string_value ("LC_TIME");
130 if (val == 0 && lc_all && *lc_all)
131 setlocale (LC_TIME, lc_all);
132# endif /* LC_TIME */
133
ccc6cda3
JA
134#endif /* HAVE_SETLOCALE */
135
136 val = get_string_value ("TEXTDOMAIN");
137 if (val && *val)
138 {
139 FREE (default_domain);
140 default_domain = savestring (val);
43c75a4e
CR
141 if (default_dir && *default_dir)
142 bindtextdomain (default_domain, default_dir);
ccc6cda3
JA
143 }
144
145 val = get_string_value ("TEXTDOMAINDIR");
146 if (val && *val)
147 {
148 FREE (default_dir);
149 default_dir = savestring (val);
5e13499c
CR
150 if (default_domain && *default_domain)
151 bindtextdomain (default_domain, default_dir);
ccc6cda3
JA
152 }
153}
154
155/* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
156 if successful, 0 otherwise. */
157int
158set_locale_var (var, value)
159 char *var, *value;
160{
d3a24ed2 161 int r;
547ef914 162 char *x;
d3a24ed2 163
547ef914
CR
164 x = "";
165 errno = 0;
ccc6cda3
JA
166 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
167 {
168 FREE (default_domain);
169 default_domain = value ? savestring (value) : (char *)NULL;
43c75a4e
CR
170 if (default_dir && *default_dir)
171 bindtextdomain (default_domain, default_dir);
ccc6cda3
JA
172 return (1);
173 }
174 else if (var[0] == 'T') /* TEXTDOMAINDIR */
175 {
176 FREE (default_dir);
177 default_dir = value ? savestring (value) : (char *)NULL;
5e13499c
CR
178 if (default_domain && *default_domain)
179 bindtextdomain (default_domain, default_dir);
ccc6cda3
JA
180 return (1);
181 }
182
183 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
184
185 else if (var[3] == 'A') /* LC_ALL */
186 {
187 FREE (lc_all);
e8ce775d
JA
188 if (value)
189 lc_all = savestring (value);
e8ce775d
JA
190 else
191 {
f73dda09 192 lc_all = (char *)xmalloc (1);
e8ce775d
JA
193 lc_all[0] = '\0';
194 }
ccc6cda3 195#if defined (HAVE_SETLOCALE)
547ef914
CR
196 r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
197 if (x == 0)
db31fb26
CR
198 {
199 if (errno == 0)
200 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
201 else
202 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
203 }
d3a24ed2 204 locale_setblanks ();
51f7ea36 205 locale_mb_cur_max = MB_CUR_MAX;
1f6ec1a8 206 u32reset ();
d3a24ed2 207 return r;
ccc6cda3
JA
208#else
209 return (1);
210#endif
211 }
212
213#if defined (HAVE_SETLOCALE)
214 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
215 {
d3a24ed2 216# if defined (LC_CTYPE)
ccc6cda3 217 if (lc_all == 0 || *lc_all == '\0')
d3a24ed2 218 {
547ef914 219 x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
d3a24ed2 220 locale_setblanks ();
51f7ea36 221 locale_mb_cur_max = MB_CUR_MAX;
1f6ec1a8 222 u32reset ();
d3a24ed2
CR
223 }
224# endif
ccc6cda3
JA
225 }
226 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
227 {
228# if defined (LC_COLLATE)
229 if (lc_all == 0 || *lc_all == '\0')
547ef914 230 x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
ccc6cda3
JA
231# endif /* LC_COLLATE */
232 }
233 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
234 {
235# if defined (LC_MESSAGES)
236 if (lc_all == 0 || *lc_all == '\0')
547ef914 237 x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
ccc6cda3
JA
238# endif /* LC_MESSAGES */
239 }
f73dda09 240 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
bb70624e
JA
241 {
242# if defined (LC_NUMERIC)
243 if (lc_all == 0 || *lc_all == '\0')
547ef914 244 x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
bb70624e
JA
245# endif /* LC_NUMERIC */
246 }
898cc92e
CR
247 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
248 {
249# if defined (LC_TIME)
250 if (lc_all == 0 || *lc_all == '\0')
547ef914 251 x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
898cc92e
CR
252# endif /* LC_TIME */
253 }
ccc6cda3 254#endif /* HAVE_SETLOCALE */
898cc92e 255
547ef914 256 if (x == 0)
db31fb26
CR
257 {
258 if (errno == 0)
259 internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
260 else
261 internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
262 }
ccc6cda3 263
547ef914 264 return (x != 0);
ccc6cda3
JA
265}
266
d3a24ed2
CR
267/* Called when LANG is assigned a value. Tracks value in `lang'. Calls
268 reset_locale_vars() to reset any default values if LC_ALL is unset or
269 null. */
ccc6cda3
JA
270int
271set_lang (var, value)
272 char *var, *value;
273{
d3a24ed2
CR
274 FREE (lang);
275 if (value)
276 lang = savestring (value);
277 else
278 {
279 lang = (char *)xmalloc (1);
280 lang[0] = '\0';
281 }
22818c14 282
d3a24ed2 283 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
ccc6cda3
JA
284}
285
d3ad40de
CR
286/* Set default values for LANG and LC_ALL. Default values for all other
287 locale-related variables depend on these. */
288void
289set_default_lang ()
290{
291 char *v;
292
293 v = get_string_value ("LC_ALL");
294 set_locale_var ("LC_ALL", v);
295
296 v = get_string_value ("LANG");
297 set_lang ("LANG", v);
298}
299
d3a24ed2
CR
300/* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
301 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
302 the specific locale variables, and LANG, if set, is used as the default. */
ccc6cda3
JA
303char *
304get_locale_var (var)
305 char *var;
306{
307 char *locale;
308
309 locale = lc_all;
310
d3a24ed2 311 if (locale == 0 || *locale == 0)
adc6cff5 312 locale = get_string_value (var); /* XXX - mem leak? */
d3a24ed2
CR
313 if (locale == 0 || *locale == 0)
314 locale = lang;
315 if (locale == 0 || *locale == 0)
d3ad40de
CR
316#if 0
317 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
318#else
319 locale = "";
320#endif
ccc6cda3
JA
321 return (locale);
322}
323
43cdcad8
CR
324/* Called to reset all of the locale variables to their appropriate values
325 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
326 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
d3a24ed2
CR
327static int
328reset_locale_vars ()
329{
d3ad40de 330 char *t;
d3a24ed2 331#if defined (HAVE_SETLOCALE)
d3ad40de
CR
332 if (lang == 0 || *lang == '\0')
333 maybe_make_export_env (); /* trust that this will change environment for setlocale */
334 if (setlocale (LC_ALL, lang ? lang : "") == 0)
d3a24ed2
CR
335 return 0;
336
337# if defined (LC_CTYPE)
d3ad40de 338 t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
d3a24ed2
CR
339# endif
340# if defined (LC_COLLATE)
d3ad40de 341 t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
d3a24ed2
CR
342# endif
343# if defined (LC_MESSAGES)
d3ad40de 344 t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
d3a24ed2
CR
345# endif
346# if defined (LC_NUMERIC)
d3ad40de 347 t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
d3a24ed2 348# endif
898cc92e 349# if defined (LC_TIME)
d3ad40de 350 t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
898cc92e 351# endif
d3a24ed2
CR
352
353 locale_setblanks ();
51f7ea36 354 locale_mb_cur_max = MB_CUR_MAX;
1f6ec1a8 355 u32reset ();
d3a24ed2
CR
356
357#endif
358 return 1;
359}
360
ccc6cda3
JA
361/* Translate the contents of STRING, a $"..." quoted string, according
362 to the current locale. In the `C' or `POSIX' locale, or if gettext()
363 is not available, the passed string is returned unchanged. The
364 length of the translated string is returned in LENP, if non-null. */
365char *
366localetrans (string, len, lenp)
367 char *string;
368 int len, *lenp;
369{
370 char *locale, *t;
ccc6cda3
JA
371 char *translated;
372 int tlen;
ccc6cda3
JA
373
374 /* Don't try to translate null strings. */
375 if (string == 0 || *string == 0)
376 {
377 if (lenp)
28ef6c31 378 *lenp = 0;
ccc6cda3
JA
379 return ((char *)NULL);
380 }
381
ccc6cda3
JA
382 locale = get_locale_var ("LC_MESSAGES");
383
384 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
385 just return the string. If we don't have gettext(), there's no use
386 doing anything else. */
ccc6cda3
JA
387 if (locale == 0 || locale[0] == '\0' ||
388 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
ccc6cda3 389 {
f73dda09 390 t = (char *)xmalloc (len + 1);
ccc6cda3
JA
391 strcpy (t, string);
392 if (lenp)
393 *lenp = len;
394 return (t);
395 }
396
ccc6cda3 397 /* Now try to translate it. */
5e13499c
CR
398 if (default_domain && *default_domain)
399 translated = dgettext (default_domain, string);
400 else
401 translated = string;
402
ccc6cda3
JA
403 if (translated == string) /* gettext returns its argument if untranslatable */
404 {
f73dda09 405 t = (char *)xmalloc (len + 1);
ccc6cda3
JA
406 strcpy (t, string);
407 if (lenp)
408 *lenp = len;
409 }
410 else
411 {
ccc6cda3 412 tlen = strlen (translated);
f73dda09 413 t = (char *)xmalloc (tlen + 1);
ccc6cda3
JA
414 strcpy (t, translated);
415 if (lenp)
416 *lenp = tlen;
417 }
418 return (t);
ccc6cda3 419}
7117c2d2
JA
420
421/* Change a bash string into a string suitable for inclusion in a `po' file.
422 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
423char *
424mk_msgstr (string, foundnlp)
425 char *string;
426 int *foundnlp;
427{
428 register int c, len;
429 char *result, *r, *s;
430
431 for (len = 0, s = string; s && *s; s++)
432 {
433 len++;
434 if (*s == '"' || *s == '\\')
435 len++;
436 else if (*s == '\n')
437 len += 5;
438 }
439
440 r = result = (char *)xmalloc (len + 3);
441 *r++ = '"';
442
443 for (s = string; s && (c = *s); s++)
444 {
445 if (c == '\n') /* <NL> -> \n"<NL>" */
446 {
447 *r++ = '\\';
448 *r++ = 'n';
449 *r++ = '"';
450 *r++ = '\n';
451 *r++ = '"';
452 if (foundnlp)
453 *foundnlp = 1;
454 continue;
455 }
456 if (c == '"' || c == '\\')
457 *r++ = '\\';
458 *r++ = c;
459 }
460
461 *r++ = '"';
462 *r++ = '\0';
463
464 return result;
465}
466
467/* $"..." -- Translate the portion of STRING between START and END
468 according to current locale using gettext (if available) and return
469 the result. The caller will take care of leaving the quotes intact.
470 The string will be left without the leading `$' by the caller.
471 If translation is performed, the translated string will be double-quoted
472 by the caller. The length of the translated string is returned in LENP,
473 if non-null. */
474char *
475localeexpand (string, start, end, lineno, lenp)
476 char *string;
477 int start, end, lineno, *lenp;
478{
479 int len, tlen, foundnl;
480 char *temp, *t, *t2;
481
482 temp = (char *)xmalloc (end - start + 1);
483 for (tlen = 0, len = start; len < end; )
484 temp[tlen++] = string[len++];
485 temp[tlen] = '\0';
486
487 /* If we're just dumping translatable strings, don't do anything with the
5e13499c
CR
488 string itself, but if we're dumping in `po' file format, convert it into
489 a form more palatable to gettext(3) and friends by quoting `"' and `\'
490 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
491 newline in TEMP, we first output a `msgid ""' line and then the
492 translated string; otherwise we output the `msgid' and translated
493 string all on one line. */
7117c2d2
JA
494 if (dump_translatable_strings)
495 {
496 if (dump_po_strings)
497 {
498 foundnl = 0;
499 t = mk_msgstr (temp, &foundnl);
500 t2 = foundnl ? "\"\"\n" : "";
501
502 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
503 yy_input_name (), lineno, t2, t);
504 free (t);
505 }
506 else
507 printf ("\"%s\"\n", temp);
508
509 if (lenp)
510 *lenp = tlen;
511 return (temp);
512 }
513 else if (*temp)
514 {
515 t = localetrans (temp, tlen, &len);
516 free (temp);
517 if (lenp)
518 *lenp = len;
519 return (t);
520 }
521 else
522 {
523 if (lenp)
524 *lenp = 0;
525 return (temp);
526 }
527}
d3a24ed2
CR
528
529/* Set every character in the <blank> character class to be a shell break
530 character for the lexical analyzer when the locale changes. */
531static void
532locale_setblanks ()
533{
534 int x;
535
536 for (x = 0; x < sh_syntabsiz; x++)
537 {
c4c90ef8 538 if (isblank ((unsigned char)x))
d3ad40de 539 sh_syntaxtab[x] |= CSHBRK|CBLANK;
d3a24ed2 540 else if (member (x, shell_break_chars))
d3ad40de
CR
541 {
542 sh_syntaxtab[x] |= CSHBRK;
543 sh_syntaxtab[x] &= ~CBLANK;
544 }
d3a24ed2 545 else
d3ad40de 546 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
d3a24ed2
CR
547 }
548}
22818c14
CR
549
550static int
551locale_isutf8 (lspec)
552 char *lspec;
553{
554 char *cp;
555
556#if HAVE_LANGINFO_CODESET
557 cp = nl_langinfo (CODESET);
558 return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
559#else
560 /* Take a shot */
561 return (strstr (lspec, "UTF-8") || strstr (lspec, "utf8"));
562#endif
563}