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 and LC_NUMERIC
75 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 #endif /* HAVE_SETLOCALE */
114 val = get_string_value ("TEXTDOMAIN");
117 FREE (default_domain);
118 default_domain = savestring (val);
120 /* Don't want to override the shell's textdomain as the default */
121 textdomain (default_domain);
125 val = get_string_value ("TEXTDOMAINDIR");
129 default_dir = savestring (val);
130 if (default_domain && *default_domain)
131 bindtextdomain (default_domain, default_dir);
135 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
136 if successful, 0 otherwise. */
138 set_locale_var (var, value)
143 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
145 FREE (default_domain);
146 default_domain = value ? savestring (value) : (char *)NULL;
148 /* Don't want to override the shell's textdomain as the default */
149 textdomain (default_domain);
153 else if (var[0] == 'T') /* TEXTDOMAINDIR */
156 default_dir = value ? savestring (value) : (char *)NULL;
157 if (default_domain && *default_domain)
158 bindtextdomain (default_domain, default_dir);
162 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
164 else if (var[3] == 'A') /* LC_ALL */
168 lc_all = savestring (value);
171 lc_all = (char *)xmalloc (1);
174 #if defined (HAVE_SETLOCALE)
175 r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
183 #if defined (HAVE_SETLOCALE)
184 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
186 # if defined (LC_CTYPE)
187 if (lc_all == 0 || *lc_all == '\0')
189 r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
195 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
197 # if defined (LC_COLLATE)
198 if (lc_all == 0 || *lc_all == '\0')
199 return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0);
200 # endif /* LC_COLLATE */
202 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
204 # if defined (LC_MESSAGES)
205 if (lc_all == 0 || *lc_all == '\0')
206 return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0);
207 # endif /* LC_MESSAGES */
209 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
211 # if defined (LC_NUMERIC)
212 if (lc_all == 0 || *lc_all == '\0')
213 return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0);
214 # endif /* LC_NUMERIC */
216 #endif /* HAVE_SETLOCALE */
221 /* Called when LANG is assigned a value. Tracks value in `lang'. Calls
222 reset_locale_vars() to reset any default values if LC_ALL is unset or
225 set_lang (var, value)
230 lang = savestring (value);
233 lang = (char *)xmalloc (1);
237 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
240 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
241 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
242 the specific locale variables, and LANG, if set, is used as the default. */
251 if (locale == 0 || *locale == 0)
252 locale = get_string_value (var);
253 if (locale == 0 || *locale == 0)
255 if (locale == 0 || *locale == 0)
256 locale = default_locale; /* system-dependent; not really portable */
261 /* Called to reset all of the locale variables to their appropriate values
262 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
263 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
267 #if defined (HAVE_SETLOCALE)
271 if (locale == 0 || *locale == '\0')
272 locale = default_locale;
273 if (setlocale (LC_ALL, locale) == 0)
276 # if defined (LC_CTYPE)
277 setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
279 # if defined (LC_COLLATE)
280 setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
282 # if defined (LC_MESSAGES)
283 setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
285 # if defined (LC_NUMERIC)
286 setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
295 /* Translate the contents of STRING, a $"..." quoted string, according
296 to the current locale. In the `C' or `POSIX' locale, or if gettext()
297 is not available, the passed string is returned unchanged. The
298 length of the translated string is returned in LENP, if non-null. */
300 localetrans (string, len, lenp)
308 /* Don't try to translate null strings. */
309 if (string == 0 || *string == 0)
313 return ((char *)NULL);
316 locale = get_locale_var ("LC_MESSAGES");
318 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
319 just return the string. If we don't have gettext(), there's no use
320 doing anything else. */
321 if (locale == 0 || locale[0] == '\0' ||
322 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
324 t = (char *)xmalloc (len + 1);
331 /* Now try to translate it. */
332 if (default_domain && *default_domain)
333 translated = dgettext (default_domain, string);
337 if (translated == string) /* gettext returns its argument if untranslatable */
339 t = (char *)xmalloc (len + 1);
346 tlen = strlen (translated);
347 t = (char *)xmalloc (tlen + 1);
348 strcpy (t, translated);
355 /* Change a bash string into a string suitable for inclusion in a `po' file.
356 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
358 mk_msgstr (string, foundnlp)
363 char *result, *r, *s;
365 for (len = 0, s = string; s && *s; s++)
368 if (*s == '"' || *s == '\\')
374 r = result = (char *)xmalloc (len + 3);
377 for (s = string; s && (c = *s); s++)
379 if (c == '\n') /* <NL> -> \n"<NL>" */
390 if (c == '"' || c == '\\')
401 /* $"..." -- Translate the portion of STRING between START and END
402 according to current locale using gettext (if available) and return
403 the result. The caller will take care of leaving the quotes intact.
404 The string will be left without the leading `$' by the caller.
405 If translation is performed, the translated string will be double-quoted
406 by the caller. The length of the translated string is returned in LENP,
409 localeexpand (string, start, end, lineno, lenp)
411 int start, end, lineno, *lenp;
413 int len, tlen, foundnl;
416 temp = (char *)xmalloc (end - start + 1);
417 for (tlen = 0, len = start; len < end; )
418 temp[tlen++] = string[len++];
421 /* If we're just dumping translatable strings, don't do anything with the
422 string itself, but if we're dumping in `po' file format, convert it into
423 a form more palatable to gettext(3) and friends by quoting `"' and `\'
424 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
425 newline in TEMP, we first output a `msgid ""' line and then the
426 translated string; otherwise we output the `msgid' and translated
427 string all on one line. */
428 if (dump_translatable_strings)
433 t = mk_msgstr (temp, &foundnl);
434 t2 = foundnl ? "\"\"\n" : "";
436 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
437 yy_input_name (), lineno, t2, t);
441 printf ("\"%s\"\n", temp);
449 t = localetrans (temp, tlen, &len);
463 /* Set every character in the <blank> character class to be a shell break
464 character for the lexical analyzer when the locale changes. */
470 for (x = 0; x < sh_syntabsiz; x++)
473 sh_syntaxtab[x] |= CSHBRK;
474 else if (member (x, shell_break_chars))
475 sh_syntaxtab[x] |= CSHBRK;
477 sh_syntaxtab[x] &= ~CSHBRK;