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 ()
82 #if defined (HAVE_SETLOCALE)
84 # if defined (LC_CTYPE)
85 val = get_string_value ("LC_CTYPE");
86 if (val == 0 && lc_all && *lc_all)
88 setlocale (LC_CTYPE, lc_all);
93 # if defined (LC_COLLATE)
94 val = get_string_value ("LC_COLLATE");
95 if (val == 0 && lc_all && *lc_all)
96 setlocale (LC_COLLATE, lc_all);
97 # endif /* LC_COLLATE */
99 # if defined (LC_MESSAGES)
100 val = get_string_value ("LC_MESSAGES");
101 if (val == 0 && lc_all && *lc_all)
102 setlocale (LC_MESSAGES, lc_all);
103 # endif /* LC_MESSAGES */
105 # if defined (LC_NUMERIC)
106 val = get_string_value ("LC_NUMERIC");
107 if (val == 0 && lc_all && *lc_all)
108 setlocale (LC_NUMERIC, lc_all);
109 # endif /* LC_NUMERIC */
111 # if defined (LC_TIME)
112 val = get_string_value ("LC_TIME");
113 if (val == 0 && lc_all && *lc_all)
114 setlocale (LC_TIME, lc_all);
115 # endif /* LC_TIME */
117 #endif /* HAVE_SETLOCALE */
119 val = get_string_value ("TEXTDOMAIN");
122 FREE (default_domain);
123 default_domain = savestring (val);
125 /* Don't want to override the shell's textdomain as the default */
126 textdomain (default_domain);
130 val = get_string_value ("TEXTDOMAINDIR");
134 default_dir = savestring (val);
135 if (default_domain && *default_domain)
136 bindtextdomain (default_domain, default_dir);
140 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
141 if successful, 0 otherwise. */
143 set_locale_var (var, value)
148 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
150 FREE (default_domain);
151 default_domain = value ? savestring (value) : (char *)NULL;
153 /* Don't want to override the shell's textdomain as the default */
154 textdomain (default_domain);
158 else if (var[0] == 'T') /* TEXTDOMAINDIR */
161 default_dir = value ? savestring (value) : (char *)NULL;
162 if (default_domain && *default_domain)
163 bindtextdomain (default_domain, default_dir);
167 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
169 else if (var[3] == 'A') /* LC_ALL */
173 lc_all = savestring (value);
176 lc_all = (char *)xmalloc (1);
179 #if defined (HAVE_SETLOCALE)
180 r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
188 #if defined (HAVE_SETLOCALE)
189 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
191 # if defined (LC_CTYPE)
192 if (lc_all == 0 || *lc_all == '\0')
194 r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
200 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
202 # if defined (LC_COLLATE)
203 if (lc_all == 0 || *lc_all == '\0')
204 return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0);
205 # endif /* LC_COLLATE */
207 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
209 # if defined (LC_MESSAGES)
210 if (lc_all == 0 || *lc_all == '\0')
211 return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0);
212 # endif /* LC_MESSAGES */
214 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
216 # if defined (LC_NUMERIC)
217 if (lc_all == 0 || *lc_all == '\0')
218 return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0);
219 # endif /* LC_NUMERIC */
221 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
223 # if defined (LC_TIME)
224 if (lc_all == 0 || *lc_all == '\0')
225 return (setlocale (LC_TIME, get_locale_var ("LC_TIME")) != 0);
226 # endif /* LC_TIME */
228 #endif /* HAVE_SETLOCALE */
234 /* Called when LANG is assigned a value. Tracks value in `lang'. Calls
235 reset_locale_vars() to reset any default values if LC_ALL is unset or
238 set_lang (var, value)
243 lang = savestring (value);
246 lang = (char *)xmalloc (1);
250 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
253 /* Set default values for LANG and LC_ALL. Default values for all other
254 locale-related variables depend on these. */
260 v = get_string_value ("LC_ALL");
261 set_locale_var ("LC_ALL", v);
263 v = get_string_value ("LANG");
264 set_lang ("LANG", v);
267 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
268 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
269 the specific locale variables, and LANG, if set, is used as the default. */
278 if (locale == 0 || *locale == 0)
279 locale = get_string_value (var);
280 if (locale == 0 || *locale == 0)
282 if (locale == 0 || *locale == 0)
283 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
288 /* Called to reset all of the locale variables to their appropriate values
289 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
290 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
294 #if defined (HAVE_SETLOCALE)
295 if (lang == 0 || *lang == '\0')
296 maybe_make_export_env (); /* trust that this will change environment for setlocale */
297 if (setlocale (LC_ALL, lang ? lang : "") == 0)
300 # if defined (LC_CTYPE)
301 setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
303 # if defined (LC_COLLATE)
304 setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
306 # if defined (LC_MESSAGES)
307 setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
309 # if defined (LC_NUMERIC)
310 setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
312 # if defined (LC_TIME)
313 setlocale (LC_TIME, get_locale_var ("LC_TIME"));
322 /* Translate the contents of STRING, a $"..." quoted string, according
323 to the current locale. In the `C' or `POSIX' locale, or if gettext()
324 is not available, the passed string is returned unchanged. The
325 length of the translated string is returned in LENP, if non-null. */
327 localetrans (string, len, lenp)
335 /* Don't try to translate null strings. */
336 if (string == 0 || *string == 0)
340 return ((char *)NULL);
343 locale = get_locale_var ("LC_MESSAGES");
345 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
346 just return the string. If we don't have gettext(), there's no use
347 doing anything else. */
348 if (locale == 0 || locale[0] == '\0' ||
349 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
351 t = (char *)xmalloc (len + 1);
358 /* Now try to translate it. */
359 if (default_domain && *default_domain)
360 translated = dgettext (default_domain, string);
364 if (translated == string) /* gettext returns its argument if untranslatable */
366 t = (char *)xmalloc (len + 1);
373 tlen = strlen (translated);
374 t = (char *)xmalloc (tlen + 1);
375 strcpy (t, translated);
382 /* Change a bash string into a string suitable for inclusion in a `po' file.
383 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
385 mk_msgstr (string, foundnlp)
390 char *result, *r, *s;
392 for (len = 0, s = string; s && *s; s++)
395 if (*s == '"' || *s == '\\')
401 r = result = (char *)xmalloc (len + 3);
404 for (s = string; s && (c = *s); s++)
406 if (c == '\n') /* <NL> -> \n"<NL>" */
417 if (c == '"' || c == '\\')
428 /* $"..." -- Translate the portion of STRING between START and END
429 according to current locale using gettext (if available) and return
430 the result. The caller will take care of leaving the quotes intact.
431 The string will be left without the leading `$' by the caller.
432 If translation is performed, the translated string will be double-quoted
433 by the caller. The length of the translated string is returned in LENP,
436 localeexpand (string, start, end, lineno, lenp)
438 int start, end, lineno, *lenp;
440 int len, tlen, foundnl;
443 temp = (char *)xmalloc (end - start + 1);
444 for (tlen = 0, len = start; len < end; )
445 temp[tlen++] = string[len++];
448 /* If we're just dumping translatable strings, don't do anything with the
449 string itself, but if we're dumping in `po' file format, convert it into
450 a form more palatable to gettext(3) and friends by quoting `"' and `\'
451 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
452 newline in TEMP, we first output a `msgid ""' line and then the
453 translated string; otherwise we output the `msgid' and translated
454 string all on one line. */
455 if (dump_translatable_strings)
460 t = mk_msgstr (temp, &foundnl);
461 t2 = foundnl ? "\"\"\n" : "";
463 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
464 yy_input_name (), lineno, t2, t);
468 printf ("\"%s\"\n", temp);
476 t = localetrans (temp, tlen, &len);
490 /* Set every character in the <blank> character class to be a shell break
491 character for the lexical analyzer when the locale changes. */
497 for (x = 0; x < sh_syntabsiz; x++)
500 sh_syntaxtab[x] |= CSHBRK|CBLANK;
501 else if (member (x, shell_break_chars))
503 sh_syntaxtab[x] |= CSHBRK;
504 sh_syntaxtab[x] &= ~CBLANK;
507 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);