1 /* locale.c - Miscellaneous internationalization functions. */
3 /* Copyright (C) 1996-2009,2012 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)
29 #if HAVE_LANGINFO_CODESET
30 # include <langinfo.h>
36 #include "chartypes.h"
40 #include "input.h" /* For bash_input */
46 int locale_utf8locale; /* unused for now */
47 int locale_mb_cur_max; /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
49 extern int dump_translatable_strings, dump_po_strings;
51 /* The current locale when the program begins */
52 static char *default_locale;
54 /* The current domain for textdomain(3). */
55 static char *default_domain;
56 static char *default_dir;
58 /* tracks the value of LC_ALL; used to override values for other locale
62 /* tracks the value of LC_ALL; used to provide defaults for locale
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. */
68 static int reset_locale_vars __P((void));
70 static void locale_setblanks __P((void));
71 static int locale_isutf8 __P((char *));
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(). */
78 #if defined (HAVE_SETLOCALE)
79 default_locale = setlocale (LC_ALL, "");
81 default_locale = savestring (default_locale);
82 #endif /* HAVE_SETLOCALE */
83 bindtextdomain (PACKAGE, LOCALEDIR);
86 locale_mb_cur_max = MB_CUR_MAX;
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
91 should be called from main() after parsing the environment. */
93 set_default_locale_vars ()
97 #if defined (HAVE_SETLOCALE)
99 # if defined (LC_CTYPE)
100 val = get_string_value ("LC_CTYPE");
101 if (val == 0 && lc_all && *lc_all)
103 setlocale (LC_CTYPE, lc_all);
105 locale_mb_cur_max = MB_CUR_MAX;
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 */
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 */
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 */
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 */
134 #endif /* HAVE_SETLOCALE */
136 val = get_string_value ("TEXTDOMAIN");
139 FREE (default_domain);
140 default_domain = savestring (val);
141 if (default_dir && *default_dir)
142 bindtextdomain (default_domain, default_dir);
145 val = get_string_value ("TEXTDOMAINDIR");
149 default_dir = savestring (val);
150 if (default_domain && *default_domain)
151 bindtextdomain (default_domain, default_dir);
155 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
156 if successful, 0 otherwise. */
158 set_locale_var (var, value)
166 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
168 FREE (default_domain);
169 default_domain = value ? savestring (value) : (char *)NULL;
170 if (default_dir && *default_dir)
171 bindtextdomain (default_domain, default_dir);
174 else if (var[0] == 'T') /* TEXTDOMAINDIR */
177 default_dir = value ? savestring (value) : (char *)NULL;
178 if (default_domain && *default_domain)
179 bindtextdomain (default_domain, default_dir);
183 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
185 else if (var[3] == 'A') /* LC_ALL */
189 lc_all = savestring (value);
192 lc_all = (char *)xmalloc (1);
195 #if defined (HAVE_SETLOCALE)
196 r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
200 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
202 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
205 locale_mb_cur_max = MB_CUR_MAX;
213 #if defined (HAVE_SETLOCALE)
214 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
216 # if defined (LC_CTYPE)
217 if (lc_all == 0 || *lc_all == '\0')
219 x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
221 locale_mb_cur_max = MB_CUR_MAX;
226 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
228 # if defined (LC_COLLATE)
229 if (lc_all == 0 || *lc_all == '\0')
230 x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
231 # endif /* LC_COLLATE */
233 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
235 # if defined (LC_MESSAGES)
236 if (lc_all == 0 || *lc_all == '\0')
237 x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
238 # endif /* LC_MESSAGES */
240 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
242 # if defined (LC_NUMERIC)
243 if (lc_all == 0 || *lc_all == '\0')
244 x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
245 # endif /* LC_NUMERIC */
247 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
249 # if defined (LC_TIME)
250 if (lc_all == 0 || *lc_all == '\0')
251 x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
252 # endif /* LC_TIME */
254 #endif /* HAVE_SETLOCALE */
259 internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
261 internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
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
271 set_lang (var, value)
276 lang = savestring (value);
279 lang = (char *)xmalloc (1);
283 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
286 /* Set default values for LANG and LC_ALL. Default values for all other
287 locale-related variables depend on these. */
293 v = get_string_value ("LC_ALL");
294 set_locale_var ("LC_ALL", v);
296 v = get_string_value ("LANG");
297 set_lang ("LANG", v);
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. */
311 if (locale == 0 || *locale == 0)
312 locale = get_string_value (var); /* XXX - mem leak? */
313 if (locale == 0 || *locale == 0)
315 if (locale == 0 || *locale == 0)
317 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
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. */
331 #if defined (HAVE_SETLOCALE)
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)
337 # if defined (LC_CTYPE)
338 t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
340 # if defined (LC_COLLATE)
341 t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
343 # if defined (LC_MESSAGES)
344 t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
346 # if defined (LC_NUMERIC)
347 t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
349 # if defined (LC_TIME)
350 t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
354 locale_mb_cur_max = MB_CUR_MAX;
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. */
366 localetrans (string, len, lenp)
374 /* Don't try to translate null strings. */
375 if (string == 0 || *string == 0)
379 return ((char *)NULL);
382 locale = get_locale_var ("LC_MESSAGES");
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. */
387 if (locale == 0 || locale[0] == '\0' ||
388 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
390 t = (char *)xmalloc (len + 1);
397 /* Now try to translate it. */
398 if (default_domain && *default_domain)
399 translated = dgettext (default_domain, string);
403 if (translated == string) /* gettext returns its argument if untranslatable */
405 t = (char *)xmalloc (len + 1);
412 tlen = strlen (translated);
413 t = (char *)xmalloc (tlen + 1);
414 strcpy (t, translated);
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". */
424 mk_msgstr (string, foundnlp)
429 char *result, *r, *s;
431 for (len = 0, s = string; s && *s; s++)
434 if (*s == '"' || *s == '\\')
440 r = result = (char *)xmalloc (len + 3);
443 for (s = string; s && (c = *s); s++)
445 if (c == '\n') /* <NL> -> \n"<NL>" */
456 if (c == '"' || c == '\\')
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,
475 localeexpand (string, start, end, lineno, lenp)
477 int start, end, lineno, *lenp;
479 int len, tlen, foundnl;
482 temp = (char *)xmalloc (end - start + 1);
483 for (tlen = 0, len = start; len < end; )
484 temp[tlen++] = string[len++];
487 /* If we're just dumping translatable strings, don't do anything with the
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. */
494 if (dump_translatable_strings)
499 t = mk_msgstr (temp, &foundnl);
500 t2 = foundnl ? "\"\"\n" : "";
502 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
503 yy_input_name (), lineno, t2, t);
507 printf ("\"%s\"\n", temp);
515 t = localetrans (temp, tlen, &len);
529 /* Set every character in the <blank> character class to be a shell break
530 character for the lexical analyzer when the locale changes. */
536 for (x = 0; x < sh_syntabsiz; x++)
539 sh_syntaxtab[x] |= CSHBRK|CBLANK;
540 else if (member (x, shell_break_chars))
542 sh_syntaxtab[x] |= CSHBRK;
543 sh_syntaxtab[x] &= ~CBLANK;
546 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
551 locale_isutf8 (lspec)
556 #if HAVE_LANGINFO_CODESET
557 cp = nl_langinfo (CODESET);
558 return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
561 return (strstr (lspec, "UTF-8") || strstr (lspec, "utf8"));