0c4772a9f10f0d4664933023a3038d5db90814a5
[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 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. */
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 #endif /* HAVE_SETLOCALE */
113
114   val = get_string_value ("TEXTDOMAIN");
115   if (val && *val)
116     {
117       FREE (default_domain);
118       default_domain = savestring (val);
119 #if 0
120       /* Don't want to override the shell's textdomain as the default */
121       textdomain (default_domain);
122 #endif
123     }
124
125   val = get_string_value ("TEXTDOMAINDIR");
126   if (val && *val)
127     {
128       FREE (default_dir);
129       default_dir = savestring (val);
130       if (default_domain && *default_domain)
131         bindtextdomain (default_domain, default_dir);
132     }
133 }
134
135 /* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
136   if successful, 0 otherwise. */
137 int
138 set_locale_var (var, value)
139      char *var, *value;
140 {
141   int r;
142
143   if (var[0] == 'T' && var[10] == 0)            /* TEXTDOMAIN */
144     {
145       FREE (default_domain);
146       default_domain = value ? savestring (value) : (char *)NULL;
147 #if 0
148       /* Don't want to override the shell's textdomain as the default */
149       textdomain (default_domain);
150 #endif
151       return (1);
152     }
153   else if (var[0] == 'T')                       /* TEXTDOMAINDIR */
154     {
155       FREE (default_dir);
156       default_dir = value ? savestring (value) : (char *)NULL;
157       if (default_domain && *default_domain)
158         bindtextdomain (default_domain, default_dir);
159       return (1);
160     }
161
162   /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
163
164   else if (var[3] == 'A')                       /* LC_ALL */
165     {
166       FREE (lc_all);
167       if (value)
168         lc_all = savestring (value);
169       else
170         {
171           lc_all = (char *)xmalloc (1);
172           lc_all[0] = '\0';
173         }
174 #if defined (HAVE_SETLOCALE)
175       r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
176       locale_setblanks ();
177       return r;
178 #else
179       return (1);
180 #endif
181     }
182
183 #if defined (HAVE_SETLOCALE)
184   else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
185     {
186 #  if defined (LC_CTYPE)
187       if (lc_all == 0 || *lc_all == '\0')
188         {
189           r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
190           locale_setblanks ();
191           return r;
192         }
193 #  endif
194     }
195   else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
196     {
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 */
201     }
202   else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
203     {
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 */
208     }
209   else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
210     {
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 */
215     }
216 #endif /* HAVE_SETLOCALE */
217
218   return (0);
219 }
220
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
223    null. */
224 int
225 set_lang (var, value)
226      char *var, *value;
227 {
228   FREE (lang);
229   if (value)
230     lang = savestring (value);
231   else
232     {
233       lang = (char *)xmalloc (1);
234       lang[0] = '\0';
235     }
236     
237   return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
238 }
239
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. */
243 char *
244 get_locale_var (var)
245      char *var;
246 {
247   char *locale;
248
249   locale = lc_all;
250
251   if (locale == 0 || *locale == 0)
252     locale = get_string_value (var);
253   if (locale == 0 || *locale == 0)
254     locale = lang;
255   if (locale == 0 || *locale == 0)
256     locale = default_locale;    /* system-dependent; not really portable */
257
258   return (locale);
259 }
260
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. */
264 static int
265 reset_locale_vars ()
266 {
267 #if defined (HAVE_SETLOCALE)
268   char *locale;
269
270   locale = lang;
271   if (locale == 0 || *locale == '\0')
272     locale = default_locale;
273   if (setlocale (LC_ALL, locale) == 0)
274     return 0;
275
276 #  if defined (LC_CTYPE)
277   setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
278 #  endif
279 #  if defined (LC_COLLATE)
280   setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
281 #  endif
282 #  if defined (LC_MESSAGES)
283   setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
284 #  endif
285 #  if defined (LC_NUMERIC)
286   setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
287 #  endif
288
289   locale_setblanks ();  
290
291 #endif
292   return 1;
293 }
294
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. */
299 char *
300 localetrans (string, len, lenp)
301      char *string;
302      int len, *lenp;
303 {
304   char *locale, *t;
305   char *translated;
306   int tlen;
307
308   /* Don't try to translate null strings. */
309   if (string == 0 || *string == 0)
310     {
311       if (lenp)
312         *lenp = 0;
313       return ((char *)NULL);
314     }
315
316   locale = get_locale_var ("LC_MESSAGES");
317
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"))
323     {
324       t = (char *)xmalloc (len + 1);
325       strcpy (t, string);
326       if (lenp)
327         *lenp = len;
328       return (t);
329     }
330
331   /* Now try to translate it. */
332   if (default_domain && *default_domain)
333     translated = dgettext (default_domain, string);
334   else
335     translated = string;
336
337   if (translated == string)     /* gettext returns its argument if untranslatable */
338     {
339       t = (char *)xmalloc (len + 1);
340       strcpy (t, string);
341       if (lenp)
342         *lenp = len;
343     }
344   else
345     {
346       tlen = strlen (translated);
347       t = (char *)xmalloc (tlen + 1);
348       strcpy (t, translated);
349       if (lenp)
350         *lenp = tlen;
351     }
352   return (t);
353 }
354
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". */
357 char *
358 mk_msgstr (string, foundnlp)
359      char *string;
360      int *foundnlp;
361 {
362   register int c, len;
363   char *result, *r, *s;
364
365   for (len = 0, s = string; s && *s; s++)
366     {
367       len++;
368       if (*s == '"' || *s == '\\')
369         len++;
370       else if (*s == '\n')
371         len += 5;
372     }
373   
374   r = result = (char *)xmalloc (len + 3);
375   *r++ = '"';
376
377   for (s = string; s && (c = *s); s++)
378     {
379       if (c == '\n')    /* <NL> -> \n"<NL>" */
380         {
381           *r++ = '\\';
382           *r++ = 'n';
383           *r++ = '"';
384           *r++ = '\n';
385           *r++ = '"';
386           if (foundnlp)
387             *foundnlp = 1;
388           continue;
389         }
390       if (c == '"' || c == '\\')
391         *r++ = '\\';
392       *r++ = c;
393     }
394
395   *r++ = '"';
396   *r++ = '\0';
397
398   return result;
399 }
400
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,
407    if non-null. */
408 char *
409 localeexpand (string, start, end, lineno, lenp)
410      char *string;
411      int start, end, lineno, *lenp;
412 {
413   int len, tlen, foundnl;
414   char *temp, *t, *t2;
415
416   temp = (char *)xmalloc (end - start + 1);
417   for (tlen = 0, len = start; len < end; )
418     temp[tlen++] = string[len++];
419   temp[tlen] = '\0';
420
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)
429     {
430       if (dump_po_strings)
431         {
432           foundnl = 0;
433           t = mk_msgstr (temp, &foundnl);
434           t2 = foundnl ? "\"\"\n" : "";
435
436           printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
437                         yy_input_name (), lineno, t2, t);
438           free (t);
439         }
440       else
441         printf ("\"%s\"\n", temp);
442
443       if (lenp)
444         *lenp = tlen;
445       return (temp);
446     }
447   else if (*temp)
448     {
449       t = localetrans (temp, tlen, &len);
450       free (temp);
451       if (lenp)
452         *lenp = len;
453       return (t);
454     }
455   else
456     {
457       if (lenp)
458         *lenp = 0;
459       return (temp);
460     }
461 }
462
463 /* Set every character in the <blank> character class to be a shell break
464    character for the lexical analyzer when the locale changes. */
465 static void
466 locale_setblanks ()
467 {
468   int x;
469
470   for (x = 0; x < sh_syntabsiz; x++)
471     {
472       if (isblank (x))
473         sh_syntaxtab[x] |= CSHBRK;
474       else if (member (x, shell_break_chars))
475         sh_syntaxtab[x] |= CSHBRK;
476       else
477         sh_syntaxtab[x] &= ~CSHBRK;
478     }
479 }