1 /* locale.c - Miscellaneous internationalization functions. */
3 /* Copyright (C) 1996-2004 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 it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #include "bashtypes.h"
25 #if defined (HAVE_UNISTD_H)
32 #include "chartypes.h"
35 #include "input.h" /* For bash_input */
37 extern int dump_translatable_strings, dump_po_strings;
39 /* The current locale when the program begins */
40 static char *default_locale;
42 /* The current domain for textdomain(3). */
43 static char *default_domain;
44 static char *default_dir;
46 /* tracks the value of LC_ALL; used to override values for other locale
50 /* tracks the value of LC_ALL; used to provide defaults for locale
54 /* Called to reset all of the locale variables to their appropriate values
55 if (and only if) LC_ALL has not been assigned a value. */
56 static int reset_locale_vars __P((void));
58 static void locale_setblanks __P((void));
60 /* Set the value of default_locale and make the current locale the
61 system default locale. This should be called very early in main(). */
65 #if defined (HAVE_SETLOCALE)
66 default_locale = setlocale (LC_ALL, "");
68 default_locale = savestring (default_locale);
69 #endif /* HAVE_SETLOCALE */
70 bindtextdomain (PACKAGE, LOCALEDIR);
74 /* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
75 LC_TIME if they are not specified in the environment, but LC_ALL is. This
76 should be called from main() after parsing the environment. */
78 set_default_locale_vars ()
83 #if defined (HAVE_SETLOCALE)
85 # if defined (LC_CTYPE)
86 val = get_string_value ("LC_CTYPE");
87 if (val == 0 && lc_all && *lc_all)
89 setlocale (LC_CTYPE, lc_all);
94 # if defined (LC_COLLATE)
95 val = get_string_value ("LC_COLLATE");
96 if (val == 0 && lc_all && *lc_all)
97 setlocale (LC_COLLATE, lc_all);
98 # endif /* LC_COLLATE */
100 # if defined (LC_MESSAGES)
101 val = get_string_value ("LC_MESSAGES");
102 if (val == 0 && lc_all && *lc_all)
103 setlocale (LC_MESSAGES, lc_all);
104 # endif /* LC_MESSAGES */
106 # if defined (LC_NUMERIC)
107 val = get_string_value ("LC_NUMERIC");
108 if (val == 0 && lc_all && *lc_all)
109 setlocale (LC_NUMERIC, lc_all);
110 # endif /* LC_NUMERIC */
112 # if defined (LC_TIME)
113 val = get_string_value ("LC_TIME");
114 if (val == 0 && lc_all && *lc_all)
115 setlocale (LC_TIME, lc_all);
116 # endif /* LC_TIME */
118 #endif /* HAVE_SETLOCALE */
120 val = get_string_value ("TEXTDOMAIN");
123 FREE (default_domain);
124 default_domain = savestring (val);
126 /* Don't want to override the shell's textdomain as the default */
127 textdomain (default_domain);
131 val = get_string_value ("TEXTDOMAINDIR");
135 default_dir = savestring (val);
136 if (default_domain && *default_domain)
137 bindtextdomain (default_domain, default_dir);
141 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
142 if successful, 0 otherwise. */
144 set_locale_var (var, value)
149 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
151 FREE (default_domain);
152 default_domain = value ? savestring (value) : (char *)NULL;
154 /* Don't want to override the shell's textdomain as the default */
155 textdomain (default_domain);
159 else if (var[0] == 'T') /* TEXTDOMAINDIR */
162 default_dir = value ? savestring (value) : (char *)NULL;
163 if (default_domain && *default_domain)
164 bindtextdomain (default_domain, default_dir);
168 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
170 else if (var[3] == 'A') /* LC_ALL */
174 lc_all = savestring (value);
177 lc_all = (char *)xmalloc (1);
180 #if defined (HAVE_SETLOCALE)
181 r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
189 #if defined (HAVE_SETLOCALE)
190 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
192 # if defined (LC_CTYPE)
193 if (lc_all == 0 || *lc_all == '\0')
195 r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
201 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
203 # if defined (LC_COLLATE)
204 if (lc_all == 0 || *lc_all == '\0')
205 return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0);
206 # endif /* LC_COLLATE */
208 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
210 # if defined (LC_MESSAGES)
211 if (lc_all == 0 || *lc_all == '\0')
212 return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0);
213 # endif /* LC_MESSAGES */
215 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
217 # if defined (LC_NUMERIC)
218 if (lc_all == 0 || *lc_all == '\0')
219 return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0);
220 # endif /* LC_NUMERIC */
222 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
224 # if defined (LC_TIME)
225 if (lc_all == 0 || *lc_all == '\0')
226 return (setlocale (LC_TIME, get_locale_var ("LC_TIME")) != 0);
227 # endif /* LC_TIME */
229 #endif /* HAVE_SETLOCALE */
235 /* Called when LANG is assigned a value. Tracks value in `lang'. Calls
236 reset_locale_vars() to reset any default values if LC_ALL is unset or
239 set_lang (var, value)
244 lang = savestring (value);
247 lang = (char *)xmalloc (1);
251 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
254 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
255 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
256 the specific locale variables, and LANG, if set, is used as the default. */
265 if (locale == 0 || *locale == 0)
266 locale = get_string_value (var);
267 if (locale == 0 || *locale == 0)
269 if (locale == 0 || *locale == 0)
270 locale = default_locale; /* system-dependent; not really portable */
275 /* Called to reset all of the locale variables to their appropriate values
276 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
277 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
281 #if defined (HAVE_SETLOCALE)
285 if (locale == 0 || *locale == '\0')
286 locale = default_locale;
287 if (setlocale (LC_ALL, locale) == 0)
290 # if defined (LC_CTYPE)
291 setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
293 # if defined (LC_COLLATE)
294 setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
296 # if defined (LC_MESSAGES)
297 setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
299 # if defined (LC_NUMERIC)
300 setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
302 # if defined (LC_TIME)
303 setlocale (LC_TIME, get_locale_var ("LC_TIME"));
312 /* Translate the contents of STRING, a $"..." quoted string, according
313 to the current locale. In the `C' or `POSIX' locale, or if gettext()
314 is not available, the passed string is returned unchanged. The
315 length of the translated string is returned in LENP, if non-null. */
317 localetrans (string, len, lenp)
325 /* Don't try to translate null strings. */
326 if (string == 0 || *string == 0)
330 return ((char *)NULL);
333 locale = get_locale_var ("LC_MESSAGES");
335 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
336 just return the string. If we don't have gettext(), there's no use
337 doing anything else. */
338 if (locale == 0 || locale[0] == '\0' ||
339 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
341 t = (char *)xmalloc (len + 1);
348 /* Now try to translate it. */
349 if (default_domain && *default_domain)
350 translated = dgettext (default_domain, string);
354 if (translated == string) /* gettext returns its argument if untranslatable */
356 t = (char *)xmalloc (len + 1);
363 tlen = strlen (translated);
364 t = (char *)xmalloc (tlen + 1);
365 strcpy (t, translated);
372 /* Change a bash string into a string suitable for inclusion in a `po' file.
373 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
375 mk_msgstr (string, foundnlp)
380 char *result, *r, *s;
382 for (len = 0, s = string; s && *s; s++)
385 if (*s == '"' || *s == '\\')
391 r = result = (char *)xmalloc (len + 3);
394 for (s = string; s && (c = *s); s++)
396 if (c == '\n') /* <NL> -> \n"<NL>" */
407 if (c == '"' || c == '\\')
418 /* $"..." -- Translate the portion of STRING between START and END
419 according to current locale using gettext (if available) and return
420 the result. The caller will take care of leaving the quotes intact.
421 The string will be left without the leading `$' by the caller.
422 If translation is performed, the translated string will be double-quoted
423 by the caller. The length of the translated string is returned in LENP,
426 localeexpand (string, start, end, lineno, lenp)
428 int start, end, lineno, *lenp;
430 int len, tlen, foundnl;
433 temp = (char *)xmalloc (end - start + 1);
434 for (tlen = 0, len = start; len < end; )
435 temp[tlen++] = string[len++];
438 /* If we're just dumping translatable strings, don't do anything with the
439 string itself, but if we're dumping in `po' file format, convert it into
440 a form more palatable to gettext(3) and friends by quoting `"' and `\'
441 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
442 newline in TEMP, we first output a `msgid ""' line and then the
443 translated string; otherwise we output the `msgid' and translated
444 string all on one line. */
445 if (dump_translatable_strings)
450 t = mk_msgstr (temp, &foundnl);
451 t2 = foundnl ? "\"\"\n" : "";
453 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
454 yy_input_name (), lineno, t2, t);
458 printf ("\"%s\"\n", temp);
466 t = localetrans (temp, tlen, &len);
480 /* Set every character in the <blank> character class to be a shell break
481 character for the lexical analyzer when the locale changes. */
487 for (x = 0; x < sh_syntabsiz; x++)
490 sh_syntaxtab[x] |= CSHBRK;
491 else if (member (x, shell_break_chars))
492 sh_syntaxtab[x] |= CSHBRK;
494 sh_syntaxtab[x] &= ~CSHBRK;