Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / locale.c
1 /* locale.c - Miscellaneous internationalization functions. */
2
3 /* Copyright (C) 1996-2009 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
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.
11
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.
16
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/>.
19 */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24
25 #if defined (HAVE_UNISTD_H)
26 #  include <unistd.h>
27 #endif
28
29 #include "bashintl.h"
30 #include "bashansi.h"
31 #include <stdio.h>
32 #include "chartypes.h"
33 #include <errno.h>
34
35 #include "shell.h"
36 #include "input.h"      /* For bash_input */
37
38 #ifndef errno
39 extern int errno;
40 #endif
41
42 extern int dump_translatable_strings, dump_po_strings;
43
44 /* The current locale when the program begins */
45 static char *default_locale;
46
47 /* The current domain for textdomain(3). */
48 static char *default_domain;
49 static char *default_dir;
50
51 /* tracks the value of LC_ALL; used to override values for other locale
52    categories */
53 static char *lc_all;
54
55 /* tracks the value of LC_ALL; used to provide defaults for locale
56    categories */
57 static char *lang;
58
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));
62
63 static void locale_setblanks __P((void));
64
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(). */
67 void
68 set_default_locale ()
69 {
70 #if defined (HAVE_SETLOCALE)
71   default_locale = setlocale (LC_ALL, "");
72   if (default_locale)
73     default_locale = savestring (default_locale);
74 #endif /* HAVE_SETLOCALE */
75   bindtextdomain (PACKAGE, LOCALEDIR);
76   textdomain (PACKAGE);
77 }
78
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. */
82 void
83 set_default_locale_vars ()
84 {
85   char *val;
86
87 #if defined (HAVE_SETLOCALE)
88
89 #  if defined (LC_CTYPE)
90   val = get_string_value ("LC_CTYPE");
91   if (val == 0 && lc_all && *lc_all)
92     {
93       setlocale (LC_CTYPE, lc_all);
94       locale_setblanks ();
95     }
96 #  endif
97
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 */
103
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 */
109
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 */
115
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 */
121
122 #endif /* HAVE_SETLOCALE */
123
124   val = get_string_value ("TEXTDOMAIN");
125   if (val && *val)
126     {
127       FREE (default_domain);
128       default_domain = savestring (val);
129 #if 0
130       /* Don't want to override the shell's textdomain as the default */
131       textdomain (default_domain);
132 #endif
133     }
134
135   val = get_string_value ("TEXTDOMAINDIR");
136   if (val && *val)
137     {
138       FREE (default_dir);
139       default_dir = savestring (val);
140       if (default_domain && *default_domain)
141         bindtextdomain (default_domain, default_dir);
142     }
143 }
144
145 /* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
146   if successful, 0 otherwise. */
147 int
148 set_locale_var (var, value)
149      char *var, *value;
150 {
151   int r;
152   char *x;
153
154   x = "";
155   errno = 0;
156   if (var[0] == 'T' && var[10] == 0)            /* TEXTDOMAIN */
157     {
158       FREE (default_domain);
159       default_domain = value ? savestring (value) : (char *)NULL;
160 #if 0
161       /* Don't want to override the shell's textdomain as the default */
162       textdomain (default_domain);
163 #endif
164       return (1);
165     }
166   else if (var[0] == 'T')                       /* TEXTDOMAINDIR */
167     {
168       FREE (default_dir);
169       default_dir = value ? savestring (value) : (char *)NULL;
170       if (default_domain && *default_domain)
171         bindtextdomain (default_domain, default_dir);
172       return (1);
173     }
174
175   /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
176
177   else if (var[3] == 'A')                       /* LC_ALL */
178     {
179       FREE (lc_all);
180       if (value)
181         lc_all = savestring (value);
182       else
183         {
184           lc_all = (char *)xmalloc (1);
185           lc_all[0] = '\0';
186         }
187 #if defined (HAVE_SETLOCALE)
188       r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
189       if (x == 0)
190         internal_warning("setlocale: LC_ALL: cannot change locale (%s): %s", lc_all, strerror(errno));
191       locale_setblanks ();
192       return r;
193 #else
194       return (1);
195 #endif
196     }
197
198 #if defined (HAVE_SETLOCALE)
199   else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
200     {
201 #  if defined (LC_CTYPE)
202       if (lc_all == 0 || *lc_all == '\0')
203         {
204           x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
205           locale_setblanks ();
206         }
207 #  endif
208     }
209   else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
210     {
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 */
215     }
216   else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
217     {
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 */
222     }
223   else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
224     {
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 */
229     }
230   else if (var[3] == 'T' && var[4] == 'I')      /* LC_TIME */
231     {
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 */
236     }
237 #endif /* HAVE_SETLOCALE */
238   
239   if (x == 0)
240     internal_warning("setlocale: %s: cannot change locale (%s): %s", var, get_locale_var (var), strerror(errno));
241
242   return (x != 0);
243 }
244
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
247    null. */
248 int
249 set_lang (var, value)
250      char *var, *value;
251 {
252   FREE (lang);
253   if (value)
254     lang = savestring (value);
255   else
256     {
257       lang = (char *)xmalloc (1);
258       lang[0] = '\0';
259     }
260     
261   return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
262 }
263
264 /* Set default values for LANG and LC_ALL.  Default values for all other
265    locale-related variables depend on these. */
266 void
267 set_default_lang ()
268 {
269   char *v;
270
271   v = get_string_value ("LC_ALL");
272   set_locale_var ("LC_ALL", v);
273
274   v = get_string_value ("LANG");
275   set_lang ("LANG", v);
276 }
277
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. */
281 char *
282 get_locale_var (var)
283      char *var;
284 {
285   char *locale;
286
287   locale = lc_all;
288
289   if (locale == 0 || *locale == 0)
290     locale = get_string_value (var);
291   if (locale == 0 || *locale == 0)
292     locale = lang;
293   if (locale == 0 || *locale == 0)
294 #if 0
295     locale = default_locale;    /* system-dependent; not really portable.  should it be "C"? */
296 #else
297     locale = "";
298 #endif
299   return (locale);
300 }
301
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. */
305 static int
306 reset_locale_vars ()
307 {
308   char *t;
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)
313     return 0;
314
315 #  if defined (LC_CTYPE)
316   t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
317 #  endif
318 #  if defined (LC_COLLATE)
319   t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
320 #  endif
321 #  if defined (LC_MESSAGES)
322   t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
323 #  endif
324 #  if defined (LC_NUMERIC)
325   t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
326 #  endif
327 #  if defined (LC_TIME)
328   t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
329 #  endif
330
331   locale_setblanks ();  
332
333 #endif
334   return 1;
335 }
336
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. */
341 char *
342 localetrans (string, len, lenp)
343      char *string;
344      int len, *lenp;
345 {
346   char *locale, *t;
347   char *translated;
348   int tlen;
349
350   /* Don't try to translate null strings. */
351   if (string == 0 || *string == 0)
352     {
353       if (lenp)
354         *lenp = 0;
355       return ((char *)NULL);
356     }
357
358   locale = get_locale_var ("LC_MESSAGES");
359
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"))
365     {
366       t = (char *)xmalloc (len + 1);
367       strcpy (t, string);
368       if (lenp)
369         *lenp = len;
370       return (t);
371     }
372
373   /* Now try to translate it. */
374   if (default_domain && *default_domain)
375     translated = dgettext (default_domain, string);
376   else
377     translated = string;
378
379   if (translated == string)     /* gettext returns its argument if untranslatable */
380     {
381       t = (char *)xmalloc (len + 1);
382       strcpy (t, string);
383       if (lenp)
384         *lenp = len;
385     }
386   else
387     {
388       tlen = strlen (translated);
389       t = (char *)xmalloc (tlen + 1);
390       strcpy (t, translated);
391       if (lenp)
392         *lenp = tlen;
393     }
394   return (t);
395 }
396
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". */
399 char *
400 mk_msgstr (string, foundnlp)
401      char *string;
402      int *foundnlp;
403 {
404   register int c, len;
405   char *result, *r, *s;
406
407   for (len = 0, s = string; s && *s; s++)
408     {
409       len++;
410       if (*s == '"' || *s == '\\')
411         len++;
412       else if (*s == '\n')
413         len += 5;
414     }
415   
416   r = result = (char *)xmalloc (len + 3);
417   *r++ = '"';
418
419   for (s = string; s && (c = *s); s++)
420     {
421       if (c == '\n')    /* <NL> -> \n"<NL>" */
422         {
423           *r++ = '\\';
424           *r++ = 'n';
425           *r++ = '"';
426           *r++ = '\n';
427           *r++ = '"';
428           if (foundnlp)
429             *foundnlp = 1;
430           continue;
431         }
432       if (c == '"' || c == '\\')
433         *r++ = '\\';
434       *r++ = c;
435     }
436
437   *r++ = '"';
438   *r++ = '\0';
439
440   return result;
441 }
442
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,
449    if non-null. */
450 char *
451 localeexpand (string, start, end, lineno, lenp)
452      char *string;
453      int start, end, lineno, *lenp;
454 {
455   int len, tlen, foundnl;
456   char *temp, *t, *t2;
457
458   temp = (char *)xmalloc (end - start + 1);
459   for (tlen = 0, len = start; len < end; )
460     temp[tlen++] = string[len++];
461   temp[tlen] = '\0';
462
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)
471     {
472       if (dump_po_strings)
473         {
474           foundnl = 0;
475           t = mk_msgstr (temp, &foundnl);
476           t2 = foundnl ? "\"\"\n" : "";
477
478           printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
479                         yy_input_name (), lineno, t2, t);
480           free (t);
481         }
482       else
483         printf ("\"%s\"\n", temp);
484
485       if (lenp)
486         *lenp = tlen;
487       return (temp);
488     }
489   else if (*temp)
490     {
491       t = localetrans (temp, tlen, &len);
492       free (temp);
493       if (lenp)
494         *lenp = len;
495       return (t);
496     }
497   else
498     {
499       if (lenp)
500         *lenp = 0;
501       return (temp);
502     }
503 }
504
505 /* Set every character in the <blank> character class to be a shell break
506    character for the lexical analyzer when the locale changes. */
507 static void
508 locale_setblanks ()
509 {
510   int x;
511
512   for (x = 0; x < sh_syntabsiz; x++)
513     {
514       if (isblank (x))
515         sh_syntaxtab[x] |= CSHBRK|CBLANK;
516       else if (member (x, shell_break_chars))
517         {
518           sh_syntaxtab[x] |= CSHBRK;
519           sh_syntaxtab[x] &= ~CBLANK;
520         }
521       else
522         sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
523     }
524 }