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