722a707813f62bf99f5d623ecc1f78e0170e0551
[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         {
191           if (errno == 0)
192             internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
193           else
194             internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
195         }
196       locale_setblanks ();
197       return r;
198 #else
199       return (1);
200 #endif
201     }
202
203 #if defined (HAVE_SETLOCALE)
204   else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
205     {
206 #  if defined (LC_CTYPE)
207       if (lc_all == 0 || *lc_all == '\0')
208         {
209           x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
210           locale_setblanks ();
211         }
212 #  endif
213     }
214   else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
215     {
216 #  if defined (LC_COLLATE)
217       if (lc_all == 0 || *lc_all == '\0')
218         x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
219 #  endif /* LC_COLLATE */
220     }
221   else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
222     {
223 #  if defined (LC_MESSAGES)
224       if (lc_all == 0 || *lc_all == '\0')
225         x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
226 #  endif /* LC_MESSAGES */
227     }
228   else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
229     {
230 #  if defined (LC_NUMERIC)
231       if (lc_all == 0 || *lc_all == '\0')
232         x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
233 #  endif /* LC_NUMERIC */
234     }
235   else if (var[3] == 'T' && var[4] == 'I')      /* LC_TIME */
236     {
237 #  if defined (LC_TIME)
238       if (lc_all == 0 || *lc_all == '\0')
239         x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
240 #  endif /* LC_TIME */
241     }
242 #endif /* HAVE_SETLOCALE */
243   
244   if (x == 0)
245     {
246       if (errno == 0)
247         internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
248       else
249         internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
250     }
251
252   return (x != 0);
253 }
254
255 /* Called when LANG is assigned a value.  Tracks value in `lang'.  Calls
256    reset_locale_vars() to reset any default values if LC_ALL is unset or
257    null. */
258 int
259 set_lang (var, value)
260      char *var, *value;
261 {
262   FREE (lang);
263   if (value)
264     lang = savestring (value);
265   else
266     {
267       lang = (char *)xmalloc (1);
268       lang[0] = '\0';
269     }
270     
271   return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
272 }
273
274 /* Set default values for LANG and LC_ALL.  Default values for all other
275    locale-related variables depend on these. */
276 void
277 set_default_lang ()
278 {
279   char *v;
280
281   v = get_string_value ("LC_ALL");
282   set_locale_var ("LC_ALL", v);
283
284   v = get_string_value ("LANG");
285   set_lang ("LANG", v);
286 }
287
288 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
289    The precedence is as POSIX.2 specifies:  LC_ALL has precedence over
290    the specific locale variables, and LANG, if set, is used as the default. */
291 char *
292 get_locale_var (var)
293      char *var;
294 {
295   char *locale;
296
297   locale = lc_all;
298
299   if (locale == 0 || *locale == 0)
300     locale = get_string_value (var);    /* XXX - mem leak? */
301   if (locale == 0 || *locale == 0)
302     locale = lang;
303   if (locale == 0 || *locale == 0)
304 #if 0
305     locale = default_locale;    /* system-dependent; not really portable.  should it be "C"? */
306 #else
307     locale = "";
308 #endif
309   return (locale);
310 }
311
312 /* Called to reset all of the locale variables to their appropriate values
313    if (and only if) LC_ALL has not been assigned a value.  DO NOT CALL THIS
314    IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
315 static int
316 reset_locale_vars ()
317 {
318   char *t;
319 #if defined (HAVE_SETLOCALE)
320   if (lang == 0 || *lang == '\0')
321     maybe_make_export_env ();           /* trust that this will change environment for setlocale */
322   if (setlocale (LC_ALL, lang ? lang : "") == 0)
323     return 0;
324
325 #  if defined (LC_CTYPE)
326   t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
327 #  endif
328 #  if defined (LC_COLLATE)
329   t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
330 #  endif
331 #  if defined (LC_MESSAGES)
332   t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
333 #  endif
334 #  if defined (LC_NUMERIC)
335   t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
336 #  endif
337 #  if defined (LC_TIME)
338   t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
339 #  endif
340
341   locale_setblanks ();  
342
343 #endif
344   return 1;
345 }
346
347 /* Translate the contents of STRING, a $"..." quoted string, according
348    to the current locale.  In the `C' or `POSIX' locale, or if gettext()
349    is not available, the passed string is returned unchanged.  The
350    length of the translated string is returned in LENP, if non-null. */
351 char *
352 localetrans (string, len, lenp)
353      char *string;
354      int len, *lenp;
355 {
356   char *locale, *t;
357   char *translated;
358   int tlen;
359
360   /* Don't try to translate null strings. */
361   if (string == 0 || *string == 0)
362     {
363       if (lenp)
364         *lenp = 0;
365       return ((char *)NULL);
366     }
367
368   locale = get_locale_var ("LC_MESSAGES");
369
370   /* If we don't have setlocale() or the current locale is `C' or `POSIX',
371      just return the string.  If we don't have gettext(), there's no use
372      doing anything else. */
373   if (locale == 0 || locale[0] == '\0' ||
374       (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
375     {
376       t = (char *)xmalloc (len + 1);
377       strcpy (t, string);
378       if (lenp)
379         *lenp = len;
380       return (t);
381     }
382
383   /* Now try to translate it. */
384   if (default_domain && *default_domain)
385     translated = dgettext (default_domain, string);
386   else
387     translated = string;
388
389   if (translated == string)     /* gettext returns its argument if untranslatable */
390     {
391       t = (char *)xmalloc (len + 1);
392       strcpy (t, string);
393       if (lenp)
394         *lenp = len;
395     }
396   else
397     {
398       tlen = strlen (translated);
399       t = (char *)xmalloc (tlen + 1);
400       strcpy (t, translated);
401       if (lenp)
402         *lenp = tlen;
403     }
404   return (t);
405 }
406
407 /* Change a bash string into a string suitable for inclusion in a `po' file.
408    This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
409 char *
410 mk_msgstr (string, foundnlp)
411      char *string;
412      int *foundnlp;
413 {
414   register int c, len;
415   char *result, *r, *s;
416
417   for (len = 0, s = string; s && *s; s++)
418     {
419       len++;
420       if (*s == '"' || *s == '\\')
421         len++;
422       else if (*s == '\n')
423         len += 5;
424     }
425   
426   r = result = (char *)xmalloc (len + 3);
427   *r++ = '"';
428
429   for (s = string; s && (c = *s); s++)
430     {
431       if (c == '\n')    /* <NL> -> \n"<NL>" */
432         {
433           *r++ = '\\';
434           *r++ = 'n';
435           *r++ = '"';
436           *r++ = '\n';
437           *r++ = '"';
438           if (foundnlp)
439             *foundnlp = 1;
440           continue;
441         }
442       if (c == '"' || c == '\\')
443         *r++ = '\\';
444       *r++ = c;
445     }
446
447   *r++ = '"';
448   *r++ = '\0';
449
450   return result;
451 }
452
453 /* $"..." -- Translate the portion of STRING between START and END
454    according to current locale using gettext (if available) and return
455    the result.  The caller will take care of leaving the quotes intact.
456    The string will be left without the leading `$' by the caller.
457    If translation is performed, the translated string will be double-quoted
458    by the caller.  The length of the translated string is returned in LENP,
459    if non-null. */
460 char *
461 localeexpand (string, start, end, lineno, lenp)
462      char *string;
463      int start, end, lineno, *lenp;
464 {
465   int len, tlen, foundnl;
466   char *temp, *t, *t2;
467
468   temp = (char *)xmalloc (end - start + 1);
469   for (tlen = 0, len = start; len < end; )
470     temp[tlen++] = string[len++];
471   temp[tlen] = '\0';
472
473   /* If we're just dumping translatable strings, don't do anything with the
474      string itself, but if we're dumping in `po' file format, convert it into
475      a form more palatable to gettext(3) and friends by quoting `"' and `\'
476      with backslashes and converting <NL> into `\n"<NL>"'.  If we find a
477      newline in TEMP, we first output a `msgid ""' line and then the
478      translated string; otherwise we output the `msgid' and translated
479      string all on one line. */
480   if (dump_translatable_strings)
481     {
482       if (dump_po_strings)
483         {
484           foundnl = 0;
485           t = mk_msgstr (temp, &foundnl);
486           t2 = foundnl ? "\"\"\n" : "";
487
488           printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
489                         yy_input_name (), lineno, t2, t);
490           free (t);
491         }
492       else
493         printf ("\"%s\"\n", temp);
494
495       if (lenp)
496         *lenp = tlen;
497       return (temp);
498     }
499   else if (*temp)
500     {
501       t = localetrans (temp, tlen, &len);
502       free (temp);
503       if (lenp)
504         *lenp = len;
505       return (t);
506     }
507   else
508     {
509       if (lenp)
510         *lenp = 0;
511       return (temp);
512     }
513 }
514
515 /* Set every character in the <blank> character class to be a shell break
516    character for the lexical analyzer when the locale changes. */
517 static void
518 locale_setblanks ()
519 {
520   int x;
521
522   for (x = 0; x < sh_syntabsiz; x++)
523     {
524       if (isblank (x))
525         sh_syntaxtab[x] |= CSHBRK|CBLANK;
526       else if (member (x, shell_break_chars))
527         {
528           sh_syntaxtab[x] |= CSHBRK;
529           sh_syntaxtab[x] &= ~CBLANK;
530         }
531       else
532         sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
533     }
534 }