1 /* locale.c - Miscellaneous internationalization functions. */
3 /* Copyright (C) 1996-2009 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
23 #include "bashtypes.h"
25 #if defined (HAVE_UNISTD_H)
32 #include "chartypes.h"
36 #include "input.h" /* For bash_input */
42 extern int dump_translatable_strings, dump_po_strings;
44 /* The current locale when the program begins */
45 static char *default_locale;
47 /* The current domain for textdomain(3). */
48 static char *default_domain;
49 static char *default_dir;
51 /* tracks the value of LC_ALL; used to override values for other locale
55 /* tracks the value of LC_ALL; used to provide defaults for locale
59 /* Called to reset all of the locale variables to their appropriate values
60 if (and only if) LC_ALL has not been assigned a value. */
61 static int reset_locale_vars __P((void));
63 static void locale_setblanks __P((void));
65 /* Set the value of default_locale and make the current locale the
66 system default locale. This should be called very early in main(). */
70 #if defined (HAVE_SETLOCALE)
71 default_locale = setlocale (LC_ALL, "");
73 default_locale = savestring (default_locale);
74 #endif /* HAVE_SETLOCALE */
75 bindtextdomain (PACKAGE, LOCALEDIR);
79 /* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
80 LC_TIME if they are not specified in the environment, but LC_ALL is. This
81 should be called from main() after parsing the environment. */
83 set_default_locale_vars ()
87 #if defined (HAVE_SETLOCALE)
89 # if defined (LC_CTYPE)
90 val = get_string_value ("LC_CTYPE");
91 if (val == 0 && lc_all && *lc_all)
93 setlocale (LC_CTYPE, lc_all);
98 # if defined (LC_COLLATE)
99 val = get_string_value ("LC_COLLATE");
100 if (val == 0 && lc_all && *lc_all)
101 setlocale (LC_COLLATE, lc_all);
102 # endif /* LC_COLLATE */
104 # if defined (LC_MESSAGES)
105 val = get_string_value ("LC_MESSAGES");
106 if (val == 0 && lc_all && *lc_all)
107 setlocale (LC_MESSAGES, lc_all);
108 # endif /* LC_MESSAGES */
110 # if defined (LC_NUMERIC)
111 val = get_string_value ("LC_NUMERIC");
112 if (val == 0 && lc_all && *lc_all)
113 setlocale (LC_NUMERIC, lc_all);
114 # endif /* LC_NUMERIC */
116 # if defined (LC_TIME)
117 val = get_string_value ("LC_TIME");
118 if (val == 0 && lc_all && *lc_all)
119 setlocale (LC_TIME, lc_all);
120 # endif /* LC_TIME */
122 #endif /* HAVE_SETLOCALE */
124 val = get_string_value ("TEXTDOMAIN");
127 FREE (default_domain);
128 default_domain = savestring (val);
130 /* Don't want to override the shell's textdomain as the default */
131 textdomain (default_domain);
135 val = get_string_value ("TEXTDOMAINDIR");
139 default_dir = savestring (val);
140 if (default_domain && *default_domain)
141 bindtextdomain (default_domain, default_dir);
145 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
146 if successful, 0 otherwise. */
148 set_locale_var (var, value)
156 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
158 FREE (default_domain);
159 default_domain = value ? savestring (value) : (char *)NULL;
161 /* Don't want to override the shell's textdomain as the default */
162 textdomain (default_domain);
166 else if (var[0] == 'T') /* TEXTDOMAINDIR */
169 default_dir = value ? savestring (value) : (char *)NULL;
170 if (default_domain && *default_domain)
171 bindtextdomain (default_domain, default_dir);
175 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
177 else if (var[3] == 'A') /* LC_ALL */
181 lc_all = savestring (value);
184 lc_all = (char *)xmalloc (1);
187 #if defined (HAVE_SETLOCALE)
188 r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
190 internal_warning("setlocale: LC_ALL: cannot change locale (%s): %s", lc_all, strerror(errno));
198 #if defined (HAVE_SETLOCALE)
199 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
201 # if defined (LC_CTYPE)
202 if (lc_all == 0 || *lc_all == '\0')
204 x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
209 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
211 # if defined (LC_COLLATE)
212 if (lc_all == 0 || *lc_all == '\0')
213 x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
214 # endif /* LC_COLLATE */
216 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
218 # if defined (LC_MESSAGES)
219 if (lc_all == 0 || *lc_all == '\0')
220 x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
221 # endif /* LC_MESSAGES */
223 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
225 # if defined (LC_NUMERIC)
226 if (lc_all == 0 || *lc_all == '\0')
227 x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
228 # endif /* LC_NUMERIC */
230 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
232 # if defined (LC_TIME)
233 if (lc_all == 0 || *lc_all == '\0')
234 x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
235 # endif /* LC_TIME */
237 #endif /* HAVE_SETLOCALE */
240 internal_warning("setlocale: %s: cannot change locale (%s): %s", var, get_locale_var (var), strerror(errno));
245 /* Called when LANG is assigned a value. Tracks value in `lang'. Calls
246 reset_locale_vars() to reset any default values if LC_ALL is unset or
249 set_lang (var, value)
254 lang = savestring (value);
257 lang = (char *)xmalloc (1);
261 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
264 /* Set default values for LANG and LC_ALL. Default values for all other
265 locale-related variables depend on these. */
271 v = get_string_value ("LC_ALL");
272 set_locale_var ("LC_ALL", v);
274 v = get_string_value ("LANG");
275 set_lang ("LANG", v);
278 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
279 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
280 the specific locale variables, and LANG, if set, is used as the default. */
289 if (locale == 0 || *locale == 0)
290 locale = get_string_value (var);
291 if (locale == 0 || *locale == 0)
293 if (locale == 0 || *locale == 0)
295 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
302 /* Called to reset all of the locale variables to their appropriate values
303 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
304 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
309 #if defined (HAVE_SETLOCALE)
310 if (lang == 0 || *lang == '\0')
311 maybe_make_export_env (); /* trust that this will change environment for setlocale */
312 if (setlocale (LC_ALL, lang ? lang : "") == 0)
315 # if defined (LC_CTYPE)
316 t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
318 # if defined (LC_COLLATE)
319 t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
321 # if defined (LC_MESSAGES)
322 t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
324 # if defined (LC_NUMERIC)
325 t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
327 # if defined (LC_TIME)
328 t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
337 /* Translate the contents of STRING, a $"..." quoted string, according
338 to the current locale. In the `C' or `POSIX' locale, or if gettext()
339 is not available, the passed string is returned unchanged. The
340 length of the translated string is returned in LENP, if non-null. */
342 localetrans (string, len, lenp)
350 /* Don't try to translate null strings. */
351 if (string == 0 || *string == 0)
355 return ((char *)NULL);
358 locale = get_locale_var ("LC_MESSAGES");
360 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
361 just return the string. If we don't have gettext(), there's no use
362 doing anything else. */
363 if (locale == 0 || locale[0] == '\0' ||
364 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
366 t = (char *)xmalloc (len + 1);
373 /* Now try to translate it. */
374 if (default_domain && *default_domain)
375 translated = dgettext (default_domain, string);
379 if (translated == string) /* gettext returns its argument if untranslatable */
381 t = (char *)xmalloc (len + 1);
388 tlen = strlen (translated);
389 t = (char *)xmalloc (tlen + 1);
390 strcpy (t, translated);
397 /* Change a bash string into a string suitable for inclusion in a `po' file.
398 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
400 mk_msgstr (string, foundnlp)
405 char *result, *r, *s;
407 for (len = 0, s = string; s && *s; s++)
410 if (*s == '"' || *s == '\\')
416 r = result = (char *)xmalloc (len + 3);
419 for (s = string; s && (c = *s); s++)
421 if (c == '\n') /* <NL> -> \n"<NL>" */
432 if (c == '"' || c == '\\')
443 /* $"..." -- Translate the portion of STRING between START and END
444 according to current locale using gettext (if available) and return
445 the result. The caller will take care of leaving the quotes intact.
446 The string will be left without the leading `$' by the caller.
447 If translation is performed, the translated string will be double-quoted
448 by the caller. The length of the translated string is returned in LENP,
451 localeexpand (string, start, end, lineno, lenp)
453 int start, end, lineno, *lenp;
455 int len, tlen, foundnl;
458 temp = (char *)xmalloc (end - start + 1);
459 for (tlen = 0, len = start; len < end; )
460 temp[tlen++] = string[len++];
463 /* If we're just dumping translatable strings, don't do anything with the
464 string itself, but if we're dumping in `po' file format, convert it into
465 a form more palatable to gettext(3) and friends by quoting `"' and `\'
466 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
467 newline in TEMP, we first output a `msgid ""' line and then the
468 translated string; otherwise we output the `msgid' and translated
469 string all on one line. */
470 if (dump_translatable_strings)
475 t = mk_msgstr (temp, &foundnl);
476 t2 = foundnl ? "\"\"\n" : "";
478 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
479 yy_input_name (), lineno, t2, t);
483 printf ("\"%s\"\n", temp);
491 t = localetrans (temp, tlen, &len);
505 /* Set every character in the <blank> character class to be a shell break
506 character for the lexical analyzer when the locale changes. */
512 for (x = 0; x < sh_syntabsiz; x++)
515 sh_syntaxtab[x] |= CSHBRK|CBLANK;
516 else if (member (x, shell_break_chars))
518 sh_syntaxtab[x] |= CSHBRK;
519 sh_syntaxtab[x] &= ~CBLANK;
522 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);