No specific user configuration
[platform/upstream/bash.git] / locale.c
1 /* locale.c - Miscellaneous internationalization functions. */
2
3 /* Copyright (C) 1996-2009,2012 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 #if HAVE_LANGINFO_CODESET
30 #  include <langinfo.h>
31 #endif
32
33 #include "bashintl.h"
34 #include "bashansi.h"
35 #include <stdio.h>
36 #include "chartypes.h"
37 #include <errno.h>
38
39 #include "shell.h"
40 #include "input.h"      /* For bash_input */
41
42 #ifndef errno
43 extern int errno;
44 #endif
45
46 int locale_utf8locale;  /* unused for now */
47 int locale_mb_cur_max;  /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
48
49 extern int dump_translatable_strings, dump_po_strings;
50
51 /* The current locale when the program begins */
52 static char *default_locale;
53
54 /* The current domain for textdomain(3). */
55 static char *default_domain;
56 static char *default_dir;
57
58 /* tracks the value of LC_ALL; used to override values for other locale
59    categories */
60 static char *lc_all;
61
62 /* tracks the value of LC_ALL; used to provide defaults for locale
63    categories */
64 static char *lang;
65
66 /* Called to reset all of the locale variables to their appropriate values
67    if (and only if) LC_ALL has not been assigned a value. */
68 static int reset_locale_vars __P((void));
69
70 static void locale_setblanks __P((void));
71 static int locale_isutf8 __P((char *));
72
73 /* Set the value of default_locale and make the current locale the
74    system default locale.  This should be called very early in main(). */
75 void
76 set_default_locale ()
77 {
78 #if defined (HAVE_SETLOCALE)
79   default_locale = setlocale (LC_ALL, "");
80   if (default_locale)
81     default_locale = savestring (default_locale);
82 #endif /* HAVE_SETLOCALE */
83   bindtextdomain (PACKAGE, LOCALEDIR);
84   textdomain (PACKAGE);
85
86   locale_mb_cur_max = MB_CUR_MAX;
87 }
88
89 /* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
90    LC_TIME if they are not specified in the environment, but LC_ALL is.  This
91    should be called from main() after parsing the environment. */
92 void
93 set_default_locale_vars ()
94 {
95   char *val;
96
97 #if defined (HAVE_SETLOCALE)
98
99 #  if defined (LC_CTYPE)
100   val = get_string_value ("LC_CTYPE");
101   if (val == 0 && lc_all && *lc_all)
102     {
103       setlocale (LC_CTYPE, lc_all);
104       locale_setblanks ();
105       locale_mb_cur_max = MB_CUR_MAX;
106       u32reset ();
107     }
108 #  endif
109
110 #  if defined (LC_COLLATE)
111   val = get_string_value ("LC_COLLATE");
112   if (val == 0 && lc_all && *lc_all)
113     setlocale (LC_COLLATE, lc_all);
114 #  endif /* LC_COLLATE */
115
116 #  if defined (LC_MESSAGES)
117   val = get_string_value ("LC_MESSAGES");
118   if (val == 0 && lc_all && *lc_all)
119     setlocale (LC_MESSAGES, lc_all);
120 #  endif /* LC_MESSAGES */
121
122 #  if defined (LC_NUMERIC)
123   val = get_string_value ("LC_NUMERIC");
124   if (val == 0 && lc_all && *lc_all)
125     setlocale (LC_NUMERIC, lc_all);
126 #  endif /* LC_NUMERIC */
127
128 #  if defined (LC_TIME)
129   val = get_string_value ("LC_TIME");
130   if (val == 0 && lc_all && *lc_all)
131     setlocale (LC_TIME, lc_all);
132 #  endif /* LC_TIME */
133
134 #endif /* HAVE_SETLOCALE */
135
136   val = get_string_value ("TEXTDOMAIN");
137   if (val && *val)
138     {
139       FREE (default_domain);
140       default_domain = savestring (val);
141       if (default_dir && *default_dir)
142         bindtextdomain (default_domain, default_dir);
143     }
144
145   val = get_string_value ("TEXTDOMAINDIR");
146   if (val && *val)
147     {
148       FREE (default_dir);
149       default_dir = savestring (val);
150       if (default_domain && *default_domain)
151         bindtextdomain (default_domain, default_dir);
152     }
153 }
154
155 /* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
156   if successful, 0 otherwise. */
157 int
158 set_locale_var (var, value)
159      char *var, *value;
160 {
161   int r;
162   char *x;
163
164   x = "";
165   errno = 0;
166   if (var[0] == 'T' && var[10] == 0)            /* TEXTDOMAIN */
167     {
168       FREE (default_domain);
169       default_domain = value ? savestring (value) : (char *)NULL;
170       if (default_dir && *default_dir)
171         bindtextdomain (default_domain, default_dir);
172       return (1);
173     }
174   else if (var[0] == 'T')                       /* TEXTDOMAINDIR */
175     {
176       FREE (default_dir);
177       default_dir = value ? savestring (value) : (char *)NULL;
178       if (default_domain && *default_domain)
179         bindtextdomain (default_domain, default_dir);
180       return (1);
181     }
182
183   /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
184
185   else if (var[3] == 'A')                       /* LC_ALL */
186     {
187       FREE (lc_all);
188       if (value)
189         lc_all = savestring (value);
190       else
191         {
192           lc_all = (char *)xmalloc (1);
193           lc_all[0] = '\0';
194         }
195 #if defined (HAVE_SETLOCALE)
196       r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
197       if (x == 0)
198         {
199           if (errno == 0)
200             internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
201           else
202             internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
203         }
204       locale_setblanks ();
205       locale_mb_cur_max = MB_CUR_MAX;
206       u32reset ();
207       return r;
208 #else
209       return (1);
210 #endif
211     }
212
213 #if defined (HAVE_SETLOCALE)
214   else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
215     {
216 #  if defined (LC_CTYPE)
217       if (lc_all == 0 || *lc_all == '\0')
218         {
219           x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
220           locale_setblanks ();
221           locale_mb_cur_max = MB_CUR_MAX;
222           u32reset ();
223         }
224 #  endif
225     }
226   else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
227     {
228 #  if defined (LC_COLLATE)
229       if (lc_all == 0 || *lc_all == '\0')
230         x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
231 #  endif /* LC_COLLATE */
232     }
233   else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
234     {
235 #  if defined (LC_MESSAGES)
236       if (lc_all == 0 || *lc_all == '\0')
237         x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
238 #  endif /* LC_MESSAGES */
239     }
240   else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
241     {
242 #  if defined (LC_NUMERIC)
243       if (lc_all == 0 || *lc_all == '\0')
244         x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
245 #  endif /* LC_NUMERIC */
246     }
247   else if (var[3] == 'T' && var[4] == 'I')      /* LC_TIME */
248     {
249 #  if defined (LC_TIME)
250       if (lc_all == 0 || *lc_all == '\0')
251         x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
252 #  endif /* LC_TIME */
253     }
254 #endif /* HAVE_SETLOCALE */
255   
256   if (x == 0)
257     {
258       if (errno == 0)
259         internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
260       else
261         internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
262     }
263
264   return (x != 0);
265 }
266
267 /* Called when LANG is assigned a value.  Tracks value in `lang'.  Calls
268    reset_locale_vars() to reset any default values if LC_ALL is unset or
269    null. */
270 int
271 set_lang (var, value)
272      char *var, *value;
273 {
274   FREE (lang);
275   if (value)
276     lang = savestring (value);
277   else
278     {
279       lang = (char *)xmalloc (1);
280       lang[0] = '\0';
281     }
282
283   return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
284 }
285
286 /* Set default values for LANG and LC_ALL.  Default values for all other
287    locale-related variables depend on these. */
288 void
289 set_default_lang ()
290 {
291   char *v;
292
293   v = get_string_value ("LC_ALL");
294   set_locale_var ("LC_ALL", v);
295
296   v = get_string_value ("LANG");
297   set_lang ("LANG", v);
298 }
299
300 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
301    The precedence is as POSIX.2 specifies:  LC_ALL has precedence over
302    the specific locale variables, and LANG, if set, is used as the default. */
303 char *
304 get_locale_var (var)
305      char *var;
306 {
307   char *locale;
308
309   locale = lc_all;
310
311   if (locale == 0 || *locale == 0)
312     locale = get_string_value (var);    /* XXX - mem leak? */
313   if (locale == 0 || *locale == 0)
314     locale = lang;
315   if (locale == 0 || *locale == 0)
316 #if 0
317     locale = default_locale;    /* system-dependent; not really portable.  should it be "C"? */
318 #else
319     locale = "";
320 #endif
321   return (locale);
322 }
323
324 /* Called to reset all of the locale variables to their appropriate values
325    if (and only if) LC_ALL has not been assigned a value.  DO NOT CALL THIS
326    IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
327 static int
328 reset_locale_vars ()
329 {
330   char *t;
331 #if defined (HAVE_SETLOCALE)
332   if (lang == 0 || *lang == '\0')
333     maybe_make_export_env ();           /* trust that this will change environment for setlocale */
334   if (setlocale (LC_ALL, lang ? lang : "") == 0)
335     return 0;
336
337 #  if defined (LC_CTYPE)
338   t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
339 #  endif
340 #  if defined (LC_COLLATE)
341   t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
342 #  endif
343 #  if defined (LC_MESSAGES)
344   t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
345 #  endif
346 #  if defined (LC_NUMERIC)
347   t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
348 #  endif
349 #  if defined (LC_TIME)
350   t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
351 #  endif
352
353   locale_setblanks ();  
354   locale_mb_cur_max = MB_CUR_MAX;
355   u32reset ();
356
357 #endif
358   return 1;
359 }
360
361 /* Translate the contents of STRING, a $"..." quoted string, according
362    to the current locale.  In the `C' or `POSIX' locale, or if gettext()
363    is not available, the passed string is returned unchanged.  The
364    length of the translated string is returned in LENP, if non-null. */
365 char *
366 localetrans (string, len, lenp)
367      char *string;
368      int len, *lenp;
369 {
370   char *locale, *t;
371   char *translated;
372   int tlen;
373
374   /* Don't try to translate null strings. */
375   if (string == 0 || *string == 0)
376     {
377       if (lenp)
378         *lenp = 0;
379       return ((char *)NULL);
380     }
381
382   locale = get_locale_var ("LC_MESSAGES");
383
384   /* If we don't have setlocale() or the current locale is `C' or `POSIX',
385      just return the string.  If we don't have gettext(), there's no use
386      doing anything else. */
387   if (locale == 0 || locale[0] == '\0' ||
388       (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
389     {
390       t = (char *)xmalloc (len + 1);
391       strcpy (t, string);
392       if (lenp)
393         *lenp = len;
394       return (t);
395     }
396
397   /* Now try to translate it. */
398   if (default_domain && *default_domain)
399     translated = dgettext (default_domain, string);
400   else
401     translated = string;
402
403   if (translated == string)     /* gettext returns its argument if untranslatable */
404     {
405       t = (char *)xmalloc (len + 1);
406       strcpy (t, string);
407       if (lenp)
408         *lenp = len;
409     }
410   else
411     {
412       tlen = strlen (translated);
413       t = (char *)xmalloc (tlen + 1);
414       strcpy (t, translated);
415       if (lenp)
416         *lenp = tlen;
417     }
418   return (t);
419 }
420
421 /* Change a bash string into a string suitable for inclusion in a `po' file.
422    This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
423 char *
424 mk_msgstr (string, foundnlp)
425      char *string;
426      int *foundnlp;
427 {
428   register int c, len;
429   char *result, *r, *s;
430
431   for (len = 0, s = string; s && *s; s++)
432     {
433       len++;
434       if (*s == '"' || *s == '\\')
435         len++;
436       else if (*s == '\n')
437         len += 5;
438     }
439   
440   r = result = (char *)xmalloc (len + 3);
441   *r++ = '"';
442
443   for (s = string; s && (c = *s); s++)
444     {
445       if (c == '\n')    /* <NL> -> \n"<NL>" */
446         {
447           *r++ = '\\';
448           *r++ = 'n';
449           *r++ = '"';
450           *r++ = '\n';
451           *r++ = '"';
452           if (foundnlp)
453             *foundnlp = 1;
454           continue;
455         }
456       if (c == '"' || c == '\\')
457         *r++ = '\\';
458       *r++ = c;
459     }
460
461   *r++ = '"';
462   *r++ = '\0';
463
464   return result;
465 }
466
467 /* $"..." -- Translate the portion of STRING between START and END
468    according to current locale using gettext (if available) and return
469    the result.  The caller will take care of leaving the quotes intact.
470    The string will be left without the leading `$' by the caller.
471    If translation is performed, the translated string will be double-quoted
472    by the caller.  The length of the translated string is returned in LENP,
473    if non-null. */
474 char *
475 localeexpand (string, start, end, lineno, lenp)
476      char *string;
477      int start, end, lineno, *lenp;
478 {
479   int len, tlen, foundnl;
480   char *temp, *t, *t2;
481
482   temp = (char *)xmalloc (end - start + 1);
483   for (tlen = 0, len = start; len < end; )
484     temp[tlen++] = string[len++];
485   temp[tlen] = '\0';
486
487   /* If we're just dumping translatable strings, don't do anything with the
488      string itself, but if we're dumping in `po' file format, convert it into
489      a form more palatable to gettext(3) and friends by quoting `"' and `\'
490      with backslashes and converting <NL> into `\n"<NL>"'.  If we find a
491      newline in TEMP, we first output a `msgid ""' line and then the
492      translated string; otherwise we output the `msgid' and translated
493      string all on one line. */
494   if (dump_translatable_strings)
495     {
496       if (dump_po_strings)
497         {
498           foundnl = 0;
499           t = mk_msgstr (temp, &foundnl);
500           t2 = foundnl ? "\"\"\n" : "";
501
502           printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
503                         yy_input_name (), lineno, t2, t);
504           free (t);
505         }
506       else
507         printf ("\"%s\"\n", temp);
508
509       if (lenp)
510         *lenp = tlen;
511       return (temp);
512     }
513   else if (*temp)
514     {
515       t = localetrans (temp, tlen, &len);
516       free (temp);
517       if (lenp)
518         *lenp = len;
519       return (t);
520     }
521   else
522     {
523       if (lenp)
524         *lenp = 0;
525       return (temp);
526     }
527 }
528
529 /* Set every character in the <blank> character class to be a shell break
530    character for the lexical analyzer when the locale changes. */
531 static void
532 locale_setblanks ()
533 {
534   int x;
535
536   for (x = 0; x < sh_syntabsiz; x++)
537     {
538       if (isblank (x))
539         sh_syntaxtab[x] |= CSHBRK|CBLANK;
540       else if (member (x, shell_break_chars))
541         {
542           sh_syntaxtab[x] |= CSHBRK;
543           sh_syntaxtab[x] &= ~CBLANK;
544         }
545       else
546         sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
547     }
548 }
549
550 static int
551 locale_isutf8 (lspec)
552      char *lspec;
553 {
554   char *cp;
555
556 #if HAVE_LANGINFO_CODESET
557   cp = nl_langinfo (CODESET);
558   return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
559 #else
560   /* Take a shot */
561   return (strstr (lspec, "UTF-8") || strstr (lspec, "utf8"));
562 #endif
563 }